From eb86fa551df33109e963e2faf304b0380ac504f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?batuhan=20i=C3=A7=C3=B6z?= Date: Thu, 7 May 2026 18:06:48 +0200 Subject: [PATCH 01/17] fix(mcp): require auth for standalone HTTP server --- packages/mcp-server/src/auth.ts | 6 +++--- packages/mcp-server/src/http.ts | 2 +- packages/mcp-server/tests/auth.test.ts | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 packages/mcp-server/tests/auth.test.ts diff --git a/packages/mcp-server/src/auth.ts b/packages/mcp-server/src/auth.ts index 150450b4..56671e9b 100644 --- a/packages/mcp-server/src/auth.ts +++ b/packages/mcp-server/src/auth.ts @@ -7,7 +7,6 @@ import { McpOptions } from './options'; export const parseClientAuthHeaders = (req: IncomingMessage, required?: boolean): Partial => { if (req.headers.authorization) { const scheme = req.headers.authorization.split(' ')[0]!; - const value = req.headers.authorization.slice(scheme.length + 1); switch (scheme) { case 'Bearer': return { accessToken: req.headers.authorization.slice('Bearer '.length) }; @@ -16,14 +15,15 @@ export const parseClientAuthHeaders = (req: IncomingMessage, required?: boolean) 'Unsupported authorization scheme. Expected the "Authorization" header to be a supported scheme (Bearer).', ); } - } else if (required) { - throw new Error('Missing required Authorization header; see WWW-Authenticate header for details.'); } const accessToken = Array.isArray(req.headers['x-beeper-access-token']) ? req.headers['x-beeper-access-token'][0] : req.headers['x-beeper-access-token']; + if (!accessToken && required) { + throw new Error('Missing required Authorization header; see WWW-Authenticate header for details.'); + } return { accessToken }; }; diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 6a55c8d6..0817aa89 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -38,7 +38,7 @@ const newServer = async ({ // endpoint so clients know how to authenticate (RFC 9728). let authOptions: Partial; try { - authOptions = parseClientAuthHeaders(req, false); + authOptions = parseClientAuthHeaders(req, true); } catch (error) { const resourceIdentifier = oauthResourceIdentifier(req); res.set( diff --git a/packages/mcp-server/tests/auth.test.ts b/packages/mcp-server/tests/auth.test.ts new file mode 100644 index 00000000..c01dde0d --- /dev/null +++ b/packages/mcp-server/tests/auth.test.ts @@ -0,0 +1,24 @@ +import { IncomingMessage } from 'node:http'; +import { parseClientAuthHeaders } from '../src/auth'; + +const reqWithHeaders = (headers: IncomingMessage['headers']) => ({ headers }) as IncomingMessage; + +describe('parseClientAuthHeaders', () => { + it('returns bearer access token from Authorization header', () => { + expect(parseClientAuthHeaders(reqWithHeaders({ authorization: 'Bearer token' }), true)).toEqual({ + accessToken: 'token', + }); + }); + + it('returns x-beeper-access-token when auth is required', () => { + expect(parseClientAuthHeaders(reqWithHeaders({ 'x-beeper-access-token': 'token' }), true)).toEqual({ + accessToken: 'token', + }); + }); + + it('throws when auth is required and no token is present', () => { + expect(() => parseClientAuthHeaders(reqWithHeaders({}), true)).toThrow( + 'Missing required Authorization header', + ); + }); +}); From f34de708e01ce81a9cb6a9dcd180c44e76b4f2fd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 8 May 2026 03:42:42 +0000 Subject: [PATCH 02/17] chore: redact api-key headers in debug logs --- src/internal/utils/log.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/internal/utils/log.ts b/src/internal/utils/log.ts index 41b8cfd3..2c61df73 100644 --- a/src/internal/utils/log.ts +++ b/src/internal/utils/log.ts @@ -107,6 +107,8 @@ export const formatRequestDetails = (details: { name, ( name.toLowerCase() === 'authorization' || + name.toLowerCase() === 'api-key' || + name.toLowerCase() === 'x-api-key' || name.toLowerCase() === 'cookie' || name.toLowerCase() === 'set-cookie' ) ? From 0992c14d964830058deccef4eafad9ded14e60b4 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 02:40:47 +0000 Subject: [PATCH 03/17] ci: pin GitHub Actions to commit SHAs Pin all GitHub Actions referenced in generated workflows (both first-party `actions/*` and third-party) to immutable commit SHAs. Updating pinned actions is now a deliberate codegen-side bump rather than implicit on every workflow run. --- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/publish-npm.yml | 4 ++-- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 92d89919..3ce698f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,10 +21,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/beeper-desktop-api-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '22' @@ -43,10 +43,10 @@ jobs: contents: read id-token: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '22' @@ -61,7 +61,7 @@ jobs: github.repository == 'stainless-sdks/beeper-desktop-api-typescript' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -91,10 +91,10 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/beeper-desktop-api-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '22' diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 3b8e2b0b..76edfd1f 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -20,10 +20,10 @@ jobs: contents: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Set up Node - uses: actions/setup-node@v3 + uses: actions/setup-node@3235b876344d2a9aa001b8d1453c930bba69e610 # v3.9.1 with: node-version: '20' diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 0e12ec56..2d74c683 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'beeper/desktop-api-js' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | From 40669cb5d53274627d81fc4554d4c5d29647e373 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 11:33:14 +0000 Subject: [PATCH 04/17] feat(api): remove cli --- .stats.yml | 4 +- packages/mcp-server/src/local-docs-search.ts | 147 ------------------- 2 files changed, 2 insertions(+), 149 deletions(-) diff --git a/.stats.yml b/.stats.yml index 2dd3fee6..b85c1572 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 30 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-c08c14bb754b4cb0e02b21fabb680469368286be339dec0aaa8c69d04a1f021a.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-371238be116b1748e82f213ba35b85b0cd574f24e9d9815f73bc743478f23c99.yml openapi_spec_hash: a10246aaf7cdc33b682fc245bd5f893b -config_hash: 72f9d43b9b51a5da912e9f3730e53ae2 +config_hash: 9a5611f899a0fe46abb2a1e463e0ee60 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index e2d61606..19a9ce30 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -84,10 +84,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Focus(context.TODO(), beeperdesktopapi.FocusParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Success)\n}\n', }, - cli: { - method: '$client focus', - example: "beeper-desktop-cli focus \\\n --access-token 'My Access Token'", - }, php: { method: 'focus', example: @@ -129,10 +125,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Search(context.TODO(), beeperdesktopapi.SearchParams{\n\t\tQuery: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Results)\n}\n', }, - cli: { - method: '$client search', - example: "beeper-desktop-cli search \\\n --access-token 'My Access Token' \\\n --query x", - }, php: { method: 'search', example: @@ -173,10 +165,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccounts, err := client.Accounts.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accounts)\n}\n', }, - cli: { - method: 'accounts list', - example: "beeper-desktop-cli accounts list \\\n --access-token 'My Access Token'", - }, php: { method: 'accounts->list', example: @@ -218,11 +206,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Accounts.Contacts.Search(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactSearchParams{\n\t\t\tQuery: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Items)\n}\n', }, - cli: { - method: 'contacts search', - example: - "beeper-desktop-cli accounts:contacts search \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --query x", - }, php: { method: 'accounts->contacts->search', example: @@ -269,11 +252,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Accounts.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, - cli: { - method: 'contacts list', - example: - "beeper-desktop-cli accounts:contacts list \\\n --access-token 'My Access Token' \\\n --account-id accountID", - }, php: { method: 'accounts->contacts->list', example: @@ -314,11 +292,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Get(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatGetParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, - cli: { - method: 'chats retrieve', - example: - "beeper-desktop-cli chats retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'chats->retrieve', example: @@ -365,11 +338,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.New(context.TODO(), beeperdesktopapi.ChatNewParams{\n\t\tAccountID: "accountID",\n\t\tParticipantIDs: []string{"string"},\n\t\tType: beeperdesktopapi.ChatNewParamsTypeSingle,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat)\n}\n', }, - cli: { - method: 'chats create', - example: - "beeper-desktop-cli chats create \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --participant-id string \\\n --type single", - }, php: { method: 'chats->create', example: @@ -416,11 +384,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Start(context.TODO(), beeperdesktopapi.ChatStartParams{\n\t\tAccountID: "accountID",\n\t\tUser: beeperdesktopapi.ChatStartParamsUser{},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, - cli: { - method: 'chats start', - example: - "beeper-desktop-cli chats start \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --user '{}'", - }, php: { method: 'chats->start', example: @@ -462,10 +425,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.List(context.TODO(), beeperdesktopapi.ChatListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, - cli: { - method: 'chats list', - example: "beeper-desktop-cli chats list \\\n --access-token 'My Access Token'", - }, php: { method: 'chats->list', example: @@ -519,10 +478,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.Search(context.TODO(), beeperdesktopapi.ChatSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, - cli: { - method: 'chats search', - example: "beeper-desktop-cli chats search \\\n --access-token 'My Access Token'", - }, php: { method: 'chats->search', example: @@ -562,11 +517,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Archive(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatArchiveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, - cli: { - method: 'chats archive', - example: - "beeper-desktop-cli chats archive \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'chats->archive', example: @@ -619,11 +569,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Update(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, - cli: { - method: 'chats update', - example: - "beeper-desktop-cli chats update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'chats->update', example: @@ -664,11 +609,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkRead(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkReadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, - cli: { - method: 'chats mark_read', - example: - "beeper-desktop-cli chats mark-read \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'chats->markRead', example: @@ -709,11 +649,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkUnread(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkUnreadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, - cli: { - method: 'chats mark_unread', - example: - "beeper-desktop-cli chats mark-unread \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'chats->markUnread', example: @@ -755,11 +690,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.NotifyAnyway(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatNotifyAnywayParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, - cli: { - method: 'chats notify_anyway', - example: - "beeper-desktop-cli chats notify-anyway \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'chats->notifyAnyway', example: @@ -798,11 +728,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"time"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.New(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatReminderNewParams{\n\t\t\tReminder: beeperdesktopapi.ChatReminderNewParamsReminder{\n\t\t\t\tRemindAt: time.Now(),\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, - cli: { - method: 'reminders create', - example: - "beeper-desktop-cli chats:reminders create \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --reminder \"{remindAt: '2025-08-31T23:30:12.520Z'}\"", - }, php: { method: 'chats->reminders->create', example: @@ -841,11 +766,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.Delete(context.TODO(), "!NCdzlIaMjZUmvmvyHU:beeper.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, - cli: { - method: 'reminders delete', - example: - "beeper-desktop-cli chats:reminders delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'chats->reminders->delete', example: @@ -886,11 +806,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Messages.Reactions.Add(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.ChatMessageReactionAddParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tReactionKey: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ChatID)\n}\n', }, - cli: { - method: 'reactions add', - example: - "beeper-desktop-cli chats:messages:reactions add \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", - }, php: { method: 'chats->messages->reactions->add', example: @@ -930,11 +845,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treaction, err := client.Chats.Messages.Reactions.Delete(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.ChatMessageReactionDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tMessageID: "1343993",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reaction.ChatID)\n}\n', }, - cli: { - method: 'reactions delete', - example: - "beeper-desktop-cli chats:messages:reactions delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", - }, php: { method: 'chats->messages->reactions->delete', example: @@ -989,10 +899,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.Search(context.TODO(), beeperdesktopapi.MessageSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, - cli: { - method: 'messages search', - example: "beeper-desktop-cli messages search \\\n --access-token 'My Access Token'", - }, php: { method: 'messages->search', example: @@ -1033,11 +939,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.List(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, - cli: { - method: 'messages list', - example: - "beeper-desktop-cli messages list \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'messages->list', example: @@ -1083,11 +984,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Messages.Send(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageSendParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.PendingMessageID)\n}\n', }, - cli: { - method: 'messages send', - example: - "beeper-desktop-cli messages send \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, php: { method: 'messages->send', example: @@ -1129,11 +1025,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Get(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageGetParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message.ID)\n}\n', }, - cli: { - method: 'messages retrieve', - example: - "beeper-desktop-cli messages retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", - }, php: { method: 'messages->retrieve', example: @@ -1174,11 +1065,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Update(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageUpdateParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tText: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message)\n}\n', }, - cli: { - method: 'messages update', - example: - "beeper-desktop-cli messages update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --text x", - }, php: { method: 'messages->update', example: @@ -1218,11 +1104,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Messages.Delete(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, - cli: { - method: 'messages delete', - example: - "beeper-desktop-cli messages delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", - }, php: { method: 'messages->delete', example: @@ -1263,11 +1144,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Download(context.TODO(), beeperdesktopapi.AssetDownloadParams{\n\t\tURL: "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Error)\n}\n', }, - cli: { - method: 'assets download', - example: - "beeper-desktop-cli assets download \\\n --access-token 'My Access Token' \\\n --url mxc://example.org/Q4x9CqGz1pB3Oa6XgJ", - }, php: { method: 'assets->download', example: @@ -1309,11 +1185,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"bytes"\n\t"context"\n\t"fmt"\n\t"io"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Upload(context.TODO(), beeperdesktopapi.AssetUploadParams{\n\t\tFile: io.Reader(bytes.NewBuffer([]byte("Example data"))),\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', }, - cli: { - method: 'assets upload', - example: - "beeper-desktop-cli assets upload \\\n --access-token 'My Access Token' \\\n --file 'Example data'", - }, php: { method: 'assets->upload', example: @@ -1355,11 +1226,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.UploadBase64(context.TODO(), beeperdesktopapi.AssetUploadBase64Params{\n\t\tContent: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', }, - cli: { - method: 'assets upload_base64', - example: - "beeper-desktop-cli assets upload-base64 \\\n --access-token 'My Access Token' \\\n --content x", - }, php: { method: 'assets->uploadBase64', example: @@ -1400,10 +1266,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Serve(context.TODO(), beeperdesktopapi.AssetServeParams{\n\t\tURL: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, - cli: { - method: 'assets serve', - example: "beeper-desktop-cli assets serve \\\n --access-token 'My Access Token' \\\n --url x", - }, php: { method: 'assets->serve', example: @@ -1444,10 +1306,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tinfo, err := client.Info.Get(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", info.App)\n}\n', }, - cli: { - method: 'info retrieve', - example: "beeper-desktop-cli info retrieve \\\n --access-token 'My Access Token'", - }, php: { method: 'info->retrieve', example: @@ -1462,11 +1320,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ ]; const EMBEDDED_READMES: { language: string; content: string }[] = [ - { - language: 'cli', - content: - "# Beeper Desktop CLI\n\nThe official CLI for the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/).\n\n\n\n## Installation\n\n### Installing with Homebrew\n\n~~~sh\nbrew install beeper/tap/beeper-desktop-cli\n~~~\n\n### Installing with Go\n\nTo test or install the CLI locally, you need [Go](https://go.dev/doc/install) version 1.22 or later installed.\n\n~~~sh\ngo install 'github.com/beeper/desktop-api-cli/cmd/beeper-desktop-cli@latest'\n~~~\n\nOnce you have run `go install`, the binary is placed in your Go bin directory:\n\n- **Default location**: `$HOME/go/bin` (or `$GOPATH/bin` if GOPATH is set)\n- **Check your path**: Run `go env GOPATH` to see the base directory\n\nIf commands aren't found after installation, add the Go bin directory to your PATH:\n\n~~~sh\n# Add to your shell profile (.zshrc, .bashrc, etc.)\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n~~~\n\n\n\n### Running Locally\n\nAfter cloning the git repository for this project, you can use the\n`scripts/run` script to run the tool locally:\n\n~~~sh\n./scripts/run args...\n~~~\n\n## Usage\n\nThe CLI follows a resource-based command structure:\n\n~~~sh\nbeeper-desktop-cli [resource] [flags...]\n~~~\n\n~~~sh\nbeeper-desktop-cli chats search \\\n --access-token 'My Access Token' \\\n --account-id matrix \\\n --account-id discordgo \\\n --account-id local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --include-muted \\\n --limit 3 \\\n --type single\n~~~\n\nFor details about specific commands, use the `--help` flag.\n\n### Environment variables\n\n| Environment variable | Description | Required |\n| --------------------- | ----------------------------------------------------------------------------------------------------- | -------- |\n| `BEEPER_ACCESS_TOKEN` | Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations. | yes |\n\n### Global flags\n\n- `--access-token` - Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations. (can also be set with `BEEPER_ACCESS_TOKEN` env var)\n- `--help` - Show command line usage\n- `--debug` - Enable debug logging (includes HTTP request/response details)\n- `--version`, `-v` - Show the CLI version\n- `--base-url` - Use a custom API backend URL\n- `--format` - Change the output format (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--format-error` - Change the output format for errors (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--transform` - Transform the data output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n- `--transform-error` - Transform the error output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n\n### Passing files as arguments\n\nTo pass files to your API, you can use the `@myfile.ext` syntax:\n\n~~~bash\nbeeper-desktop-cli --arg @abe.jpg\n~~~\n\nFiles can also be passed inside JSON or YAML blobs:\n\n~~~bash\nbeeper-desktop-cli --arg '{image: \"@abe.jpg\"}'\n# Equivalent:\nbeeper-desktop-cli < --username '\\@abe'\n~~~\n\n#### Explicit encoding\n\nFor JSON endpoints, the CLI tool does filetype sniffing to determine whether the\nfile contents should be sent as a string literal (for plain text files) or as a\nbase64-encoded string literal (for binary files). If you need to explicitly send\nthe file as either plain text or base64-encoded data, you can use\n`@file://myfile.txt` (for string encoding) or `@data://myfile.dat` (for\nbase64-encoding). Note that absolute paths will begin with `@file://` or\n`@data://`, followed by a third `/` (for example, `@file:///tmp/file.txt`).\n\n~~~bash\nbeeper-desktop-cli --arg @data://file.txt\n~~~\n\n## Linking different Go SDK versions\n\nYou can link the CLI against a different version of the Beeper Desktop Go SDK\nfor development purposes using the `./scripts/link` script.\n\nTo link to a specific version from a repository (version can be a branch,\ngit tag, or commit hash):\n\n~~~bash\n./scripts/link github.com/org/repo@version\n~~~\n\nTo link to a local copy of the SDK:\n\n~~~bash\n./scripts/link ../path/to/beeperdesktopapi-go\n~~~\n\nIf you run the link script without any arguments, it will default to `../beeperdesktopapi-go`.\n", - }, { language: 'go', content: From e57f3c434130b6072e22f499ae9c3470e111b99d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 May 2026 19:56:57 +0000 Subject: [PATCH 05/17] Update Desktop API SDKs --- .stats.yml | 8 +- api.md | 250 ++ packages/mcp-server/src/code-tool-worker.ts | 42 + packages/mcp-server/src/local-docs-search.ts | 2230 ++++++++++++++++- packages/mcp-server/src/methods.ts | 259 ++ src/client.ts | 47 + src/resources/app.ts | 3 + src/resources/app/app.ts | 1727 +++++++++++++ src/resources/app/e2ee.ts | 3 + src/resources/app/e2ee/e2ee.ts | 60 + src/resources/app/e2ee/index.ts | 19 + src/resources/app/e2ee/recovery-code.ts | 3 + src/resources/app/e2ee/recovery-code/index.ts | 17 + .../app/e2ee/recovery-code/recovery-code.ts | 550 ++++ src/resources/app/e2ee/recovery-code/reset.ts | 544 ++++ src/resources/app/e2ee/verification.ts | 3 + src/resources/app/e2ee/verification/index.ts | 13 + src/resources/app/e2ee/verification/qr.ts | 529 ++++ src/resources/app/e2ee/verification/sas.ts | 518 ++++ .../app/e2ee/verification/verification.ts | 827 ++++++ src/resources/app/index.ts | 25 + src/resources/app/login.ts | 766 ++++++ src/resources/bridges.ts | 107 + src/resources/index.ts | 13 + src/resources/matrix.ts | 3 + src/resources/matrix/bridges.ts | 3 + src/resources/matrix/bridges/auth.ts | 1950 ++++++++++++++ src/resources/matrix/bridges/bridges.ts | 125 + src/resources/matrix/bridges/capabilities.ts | 45 + src/resources/matrix/bridges/contacts.ts | 94 + src/resources/matrix/bridges/index.ts | 38 + src/resources/matrix/bridges/rooms.ts | 231 ++ src/resources/matrix/bridges/users.ts | 176 ++ src/resources/matrix/index.ts | 15 + src/resources/matrix/matrix.ts | 61 + src/resources/matrix/rooms.ts | 3 + src/resources/matrix/rooms/account-data.ts | 113 + src/resources/matrix/rooms/events.ts | 148 ++ src/resources/matrix/rooms/index.ts | 28 + src/resources/matrix/rooms/rooms.ts | 435 ++++ src/resources/matrix/rooms/state.ts | 194 ++ src/resources/matrix/users.ts | 3 + src/resources/matrix/users/account-data.ts | 95 + src/resources/matrix/users/index.ts | 11 + src/resources/matrix/users/users.ts | 71 + src/resources/shared.ts | 227 ++ src/tree-shakable.ts | 4 +- tests/api-resources/app/app.test.ts | 32 + .../e2ee/recovery-code/recovery-code.test.ts | 55 + .../app/e2ee/recovery-code/reset.test.ts | 67 + .../app/e2ee/verification/qr.test.ts | 55 + .../app/e2ee/verification/sas.test.ts | 51 + .../e2ee/verification/verification.test.ts | 80 + tests/api-resources/app/login.test.ts | 95 + tests/api-resources/bridges.test.ts | 32 + .../api-resources/matrix/bridges/auth.test.ts | 166 ++ .../matrix/bridges/capabilities.test.ts | 42 + .../matrix/bridges/contacts.test.ts | 51 + .../matrix/bridges/rooms.test.ts | 74 + .../matrix/bridges/users.test.ts | 69 + .../matrix/rooms/account-data.test.ts | 73 + .../api-resources/matrix/rooms/events.test.ts | 48 + .../api-resources/matrix/rooms/rooms.test.ts | 62 + .../api-resources/matrix/rooms/state.test.ts | 62 + .../matrix/users/account-data.test.ts | 69 + .../api-resources/matrix/users/users.test.ts | 40 + 66 files changed, 13770 insertions(+), 89 deletions(-) create mode 100644 src/resources/app.ts create mode 100644 src/resources/app/app.ts create mode 100644 src/resources/app/e2ee.ts create mode 100644 src/resources/app/e2ee/e2ee.ts create mode 100644 src/resources/app/e2ee/index.ts create mode 100644 src/resources/app/e2ee/recovery-code.ts create mode 100644 src/resources/app/e2ee/recovery-code/index.ts create mode 100644 src/resources/app/e2ee/recovery-code/recovery-code.ts create mode 100644 src/resources/app/e2ee/recovery-code/reset.ts create mode 100644 src/resources/app/e2ee/verification.ts create mode 100644 src/resources/app/e2ee/verification/index.ts create mode 100644 src/resources/app/e2ee/verification/qr.ts create mode 100644 src/resources/app/e2ee/verification/sas.ts create mode 100644 src/resources/app/e2ee/verification/verification.ts create mode 100644 src/resources/app/index.ts create mode 100644 src/resources/app/login.ts create mode 100644 src/resources/bridges.ts create mode 100644 src/resources/matrix.ts create mode 100644 src/resources/matrix/bridges.ts create mode 100644 src/resources/matrix/bridges/auth.ts create mode 100644 src/resources/matrix/bridges/bridges.ts create mode 100644 src/resources/matrix/bridges/capabilities.ts create mode 100644 src/resources/matrix/bridges/contacts.ts create mode 100644 src/resources/matrix/bridges/index.ts create mode 100644 src/resources/matrix/bridges/rooms.ts create mode 100644 src/resources/matrix/bridges/users.ts create mode 100644 src/resources/matrix/index.ts create mode 100644 src/resources/matrix/matrix.ts create mode 100644 src/resources/matrix/rooms.ts create mode 100644 src/resources/matrix/rooms/account-data.ts create mode 100644 src/resources/matrix/rooms/events.ts create mode 100644 src/resources/matrix/rooms/index.ts create mode 100644 src/resources/matrix/rooms/rooms.ts create mode 100644 src/resources/matrix/rooms/state.ts create mode 100644 src/resources/matrix/users.ts create mode 100644 src/resources/matrix/users/account-data.ts create mode 100644 src/resources/matrix/users/index.ts create mode 100644 src/resources/matrix/users/users.ts create mode 100644 tests/api-resources/app/app.test.ts create mode 100644 tests/api-resources/app/e2ee/recovery-code/recovery-code.test.ts create mode 100644 tests/api-resources/app/e2ee/recovery-code/reset.test.ts create mode 100644 tests/api-resources/app/e2ee/verification/qr.test.ts create mode 100644 tests/api-resources/app/e2ee/verification/sas.test.ts create mode 100644 tests/api-resources/app/e2ee/verification/verification.test.ts create mode 100644 tests/api-resources/app/login.test.ts create mode 100644 tests/api-resources/bridges.test.ts create mode 100644 tests/api-resources/matrix/bridges/auth.test.ts create mode 100644 tests/api-resources/matrix/bridges/capabilities.test.ts create mode 100644 tests/api-resources/matrix/bridges/contacts.test.ts create mode 100644 tests/api-resources/matrix/bridges/rooms.test.ts create mode 100644 tests/api-resources/matrix/bridges/users.test.ts create mode 100644 tests/api-resources/matrix/rooms/account-data.test.ts create mode 100644 tests/api-resources/matrix/rooms/events.test.ts create mode 100644 tests/api-resources/matrix/rooms/rooms.test.ts create mode 100644 tests/api-resources/matrix/rooms/state.test.ts create mode 100644 tests/api-resources/matrix/users/account-data.test.ts create mode 100644 tests/api-resources/matrix/users/users.test.ts diff --git a/.stats.yml b/.stats.yml index b85c1572..b63d20d3 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 30 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-371238be116b1748e82f213ba35b85b0cd574f24e9d9815f73bc743478f23c99.yml -openapi_spec_hash: a10246aaf7cdc33b682fc245bd5f893b -config_hash: 9a5611f899a0fe46abb2a1e463e0ee60 +configured_endpoints: 72 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-de1370e6a3183044fa135a886d2ee8f779d5e86228cdbd503d553b4c13cc7cbe.yml +openapi_spec_hash: 30b435d7585d8b6951610e7147369779 +config_hash: 683b13ea6fb6aa9d6b1b8814cca24f1c diff --git a/api.md b/api.md index bde6c07e..e93cdecc 100644 --- a/api.md +++ b/api.md @@ -14,12 +14,109 @@ Methods: Types: +- AppStateSnapshot - Attachment - Error - Message - Reaction - User +# App + +Types: + +- LoginRegistrationRequiredResponse +- LoginResponse +- LoginResponseOutput +- RecoveryCodeResetResponse +- StartVerificationResponse +- StateMutationResponse +- AppStatusResponse + +Methods: + +- client.app.status() -> AppStatusResponse + +## Login + +Types: + +- LoginEmailResponse +- LoginRegisterResponse +- LoginResponseResponse +- LoginStartResponse + +Methods: + +- client.app.login.email({ ...params }) -> unknown +- client.app.login.register({ ...params }) -> LoginRegisterResponse +- client.app.login.response({ ...params }) -> LoginResponseResponse +- client.app.login.start() -> LoginStartResponse + +## E2ee + +### RecoveryCode + +Types: + +- RecoveryCodeMarkBackedUpResponse +- RecoveryCodeVerifyResponse + +Methods: + +- client.app.e2ee.recoveryCode.markBackedUp() -> RecoveryCodeMarkBackedUpResponse +- client.app.e2ee.recoveryCode.verify({ ...params }) -> RecoveryCodeVerifyResponse + +#### Reset + +Types: + +- ResetCreateResponse +- ResetConfirmResponse + +Methods: + +- client.app.e2ee.recoveryCode.reset.create({ ...params }) -> ResetCreateResponse +- client.app.e2ee.recoveryCode.reset.confirm({ ...params }) -> ResetConfirmResponse + +### Verification + +Types: + +- VerificationCreateResponse +- VerificationAcceptResponse +- VerificationCancelResponse + +Methods: + +- client.app.e2ee.verification.create({ ...params }) -> VerificationCreateResponse +- client.app.e2ee.verification.accept(verificationID) -> VerificationAcceptResponse +- client.app.e2ee.verification.cancel(verificationID, { ...params }) -> VerificationCancelResponse + +#### Qr + +Types: + +- QrConfirmScannedResponse +- QrScanResponse + +Methods: + +- client.app.e2ee.verification.qr.confirmScanned(verificationID) -> QrConfirmScannedResponse +- client.app.e2ee.verification.qr.scan({ ...params }) -> QrScanResponse + +#### Sas + +Types: + +- SaConfirmResponse +- SaStartResponse + +Methods: + +- client.app.e2ee.verification.sas.confirm(verificationID) -> SaConfirmResponse +- client.app.e2ee.verification.sas.start(verificationID) -> SaStartResponse + # Accounts Types: @@ -42,6 +139,159 @@ Methods: - client.accounts.contacts.list(accountID, { ...params }) -> UsersCursorSearch - client.accounts.contacts.search(accountID, { ...params }) -> ContactSearchResponse +# Bridges + +Types: + +- BridgeAvailability +- BridgeListResponse + +Methods: + +- client.bridges.list() -> BridgeListResponse + +# Matrix + +## Users + +Types: + +- UserRetrieveProfileResponse + +Methods: + +- client.matrix.users.retrieveProfile(userID) -> UserRetrieveProfileResponse + +### AccountData + +Types: + +- AccountDataRetrieveResponse +- AccountDataUpdateResponse + +Methods: + +- client.matrix.users.accountData.retrieve(type, { ...params }) -> unknown +- client.matrix.users.accountData.update(type, { ...params }) -> unknown + +## Rooms + +Types: + +- RoomCreateResponse +- RoomJoinResponse +- RoomLeaveResponse + +Methods: + +- client.matrix.rooms.create({ ...params }) -> RoomCreateResponse +- client.matrix.rooms.join(roomIDOrAlias, { ...params }) -> RoomJoinResponse +- client.matrix.rooms.leave(roomID, { ...params }) -> unknown + +### AccountData + +Types: + +- AccountDataRetrieveResponse +- AccountDataUpdateResponse + +Methods: + +- client.matrix.rooms.accountData.retrieve(type, { ...params }) -> unknown +- client.matrix.rooms.accountData.update(type, { ...params }) -> unknown + +### State + +Types: + +- StateRetrieveResponse +- StateListResponse + +Methods: + +- client.matrix.rooms.state.retrieve(stateKey, { ...params }) -> StateRetrieveResponse +- client.matrix.rooms.state.list(roomID) -> StateListResponse + +### Events + +Types: + +- EventRetrieveResponse + +Methods: + +- client.matrix.rooms.events.retrieve(eventID, { ...params }) -> EventRetrieveResponse + +## Bridges + +### Auth + +Types: + +- AuthListFlowsResponse +- AuthListLoginsResponse +- AuthLogoutResponse +- AuthStartLoginResponse +- AuthSubmitCookiesResponse +- AuthSubmitUserInputResponse +- AuthWaitForStepResponse +- AuthWhoamiResponse + +Methods: + +- client.matrix.bridges.auth.listFlows(bridgeID) -> AuthListFlowsResponse +- client.matrix.bridges.auth.listLogins(bridgeID) -> AuthListLoginsResponse +- client.matrix.bridges.auth.logout(loginID, { ...params }) -> unknown +- client.matrix.bridges.auth.startLogin(flowID, { ...params }) -> AuthStartLoginResponse +- client.matrix.bridges.auth.submitCookies(stepID, { ...params }) -> AuthSubmitCookiesResponse +- client.matrix.bridges.auth.submitUserInput(stepID, { ...params }) -> AuthSubmitUserInputResponse +- client.matrix.bridges.auth.waitForStep(stepID, { ...params }) -> AuthWaitForStepResponse +- client.matrix.bridges.auth.whoami(bridgeID) -> AuthWhoamiResponse + +### Contacts + +Types: + +- ContactListResponse + +Methods: + +- client.matrix.bridges.contacts.list(bridgeID, { ...params }) -> ContactListResponse + +### Users + +Types: + +- UserResolveResponse +- UserSearchResponse + +Methods: + +- client.matrix.bridges.users.resolve(identifier, { ...params }) -> UserResolveResponse +- client.matrix.bridges.users.search(bridgeID, { ...params }) -> UserSearchResponse + +### Rooms + +Types: + +- RoomCreateDmResponse +- RoomCreateGroupResponse + +Methods: + +- client.matrix.bridges.rooms.createDm(identifier, { ...params }) -> RoomCreateDmResponse +- client.matrix.bridges.rooms.createGroup(groupType, { ...params }) -> RoomCreateGroupResponse + +### Capabilities + +Types: + +- CapabilityRetrieveResponse + +Methods: + +- client.matrix.bridges.capabilities.retrieve(bridgeID) -> CapabilityRetrieveResponse + # Chats Types: diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index b7ad928e..fbb4d67a 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -110,9 +110,51 @@ const fuse = new Fuse( [ 'client.focus', 'client.search', + 'client.app.status', + 'client.app.login.email', + 'client.app.login.register', + 'client.app.login.response', + 'client.app.login.start', + 'client.app.e2ee.recoveryCode.markBackedUp', + 'client.app.e2ee.recoveryCode.verify', + 'client.app.e2ee.recoveryCode.reset.confirm', + 'client.app.e2ee.recoveryCode.reset.create', + 'client.app.e2ee.verification.accept', + 'client.app.e2ee.verification.cancel', + 'client.app.e2ee.verification.create', + 'client.app.e2ee.verification.qr.confirmScanned', + 'client.app.e2ee.verification.qr.scan', + 'client.app.e2ee.verification.sas.confirm', + 'client.app.e2ee.verification.sas.start', 'client.accounts.list', 'client.accounts.contacts.list', 'client.accounts.contacts.search', + 'client.bridges.list', + 'client.matrix.users.retrieveProfile', + 'client.matrix.users.accountData.retrieve', + 'client.matrix.users.accountData.update', + 'client.matrix.rooms.create', + 'client.matrix.rooms.join', + 'client.matrix.rooms.leave', + 'client.matrix.rooms.accountData.retrieve', + 'client.matrix.rooms.accountData.update', + 'client.matrix.rooms.state.list', + 'client.matrix.rooms.state.retrieve', + 'client.matrix.rooms.events.retrieve', + 'client.matrix.bridges.auth.listFlows', + 'client.matrix.bridges.auth.listLogins', + 'client.matrix.bridges.auth.logout', + 'client.matrix.bridges.auth.startLogin', + 'client.matrix.bridges.auth.submitCookies', + 'client.matrix.bridges.auth.submitUserInput', + 'client.matrix.bridges.auth.waitForStep', + 'client.matrix.bridges.auth.whoami', + 'client.matrix.bridges.contacts.list', + 'client.matrix.bridges.users.resolve', + 'client.matrix.bridges.users.search', + 'client.matrix.bridges.rooms.createDm', + 'client.matrix.bridges.rooms.createGroup', + 'client.matrix.bridges.capabilities.retrieve', 'client.chats.archive', 'client.chats.create', 'client.chats.list', diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 19a9ce30..0d902a84 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -84,182 +84,2121 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Focus(context.TODO(), beeperdesktopapi.FocusParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Success)\n}\n', }, + cli: { + method: '$client focus', + example: "beeper-desktop-cli focus \\\n --access-token 'My Access Token'", + }, + php: { + method: 'focus', + example: + "focus(\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n draftAttachmentPath: 'draftAttachmentPath',\n draftText: 'draftText',\n messageID: 'messageID',\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/focus \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'search', + endpoint: '/v1/search', + httpMethod: 'get', + summary: 'Search', + description: + 'Returns matching chats, participant name matches in groups, and the first page of messages in one call. Paginate messages via search-messages. Paginate chats via search-chats.', + stainlessPath: '(resource) $client > (method) search', + qualified: 'client.search', + params: ['query: string;'], + response: + '{ results: { chats: object[]; in_groups: object[]; messages: { chats: object; hasMore: boolean; items: message[]; newestCursor: string; oldestCursor: string; }; }; }', + markdown: + "## search\n\n`client.search(query: string): { results: object; }`\n\n**get** `/v1/search`\n\nReturns matching chats, participant name matches in groups, and the first page of messages in one call. Paginate messages via search-messages. Paginate chats via search-chats.\n\n### Parameters\n\n- `query: string`\n User-typed search text. Literal word matching (non-semantic).\n\n### Returns\n\n- `{ results: { chats: object[]; in_groups: object[]; messages: { chats: object; hasMore: boolean; items: message[]; newestCursor: string; oldestCursor: string; }; }; }`\n\n - `results: { chats: { id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }[]; in_groups: { id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }[]; messages: { chats: object; hasMore: boolean; items: { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }[]; newestCursor: string; oldestCursor: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.search({ query: 'x' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.search', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.search({ query: 'x' });\n\nconsole.log(response.results);", + }, + python: { + method: 'search', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.search(\n query="x",\n)\nprint(response.results)', + }, + go: { + method: 'client.Search', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Search(context.TODO(), beeperdesktopapi.SearchParams{\n\t\tQuery: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Results)\n}\n', + }, + cli: { + method: '$client search', + example: "beeper-desktop-cli search \\\n --access-token 'My Access Token' \\\n --query x", + }, + php: { + method: 'search', + example: + "search(query: 'x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'status', + endpoint: '/v1/app/status', + httpMethod: 'get', + summary: 'Get app onboarding status', + description: + 'Return the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.', + stainlessPath: '(resource) app > (method) status', + qualified: 'client.app.status', + response: + "{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }", + markdown: + "## status\n\n`client.app.status(): { e2ee: object; state: string; matrix?: object; verification?: object; }`\n\n**get** `/v1/app/status`\n\nReturn the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.\n\n### Returns\n\n- `{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n - `e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }`\n - `state: string`\n - `matrix?: { deviceID: string; homeserver: string; userID: string; }`\n - `verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.status();\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.status', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.status();\n\nconsole.log(response.e2ee);", + }, + python: { + method: 'app.status', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.status()\nprint(response.e2ee)', + }, + go: { + method: 'client.App.Status', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Status(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.E2ee)\n}\n', + }, + cli: { + method: 'app status', + example: "beeper-desktop-cli app status \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->status', + example: + "app->status();\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/status \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'start', + endpoint: '/v1/app/login/start', + httpMethod: 'post', + summary: 'Start app login', + description: 'Start a first-party Beeper Desktop sign-in session.', + stainlessPath: '(resource) app.login > (method) start', + qualified: 'client.app.login.start', + response: '{ request: string; type: string[]; }', + markdown: + "## start\n\n`client.app.login.start(): { request: string; type: string[]; }`\n\n**post** `/v1/app/login/start`\n\nStart a first-party Beeper Desktop sign-in session.\n\n### Returns\n\n- `{ request: string; type: string[]; }`\n\n - `request: string`\n - `type: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.start', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response.request);", + }, + python: { + method: 'app.login.start', + example: + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.start()\nprint(response.request)', + }, + go: { + method: 'client.App.Login.Start', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Start(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Request)\n}\n', + }, + cli: { + method: 'login start', + example: "beeper-desktop-cli app:login start \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->login->start', + example: + "app->login->start();\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/login/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'email', + endpoint: '/v1/app/login/email', + httpMethod: 'post', + summary: 'Send login code', + description: 'Send a sign-in code to the user email address.', + stainlessPath: '(resource) app.login > (method) email', + qualified: 'client.app.login.email', + params: ['email: string;', 'request: string;'], + response: 'object', + markdown: + "## email\n\n`client.app.login.email(email: string, request: string): object`\n\n**post** `/v1/app/login/email`\n\nSend a sign-in code to the user email address.\n\n### Parameters\n\n- `email: string`\n Email address to send the sign-in code to.\n\n- `request: string`\n Login request ID returned by the start step.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.email', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);", + }, + python: { + method: 'app.login.email', + example: + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.email(\n email="dev@stainless.com",\n request="request",\n)\nprint(response)', + }, + go: { + method: 'client.App.Login.Email', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Email(context.TODO(), beeperdesktopapi.AppLoginEmailParams{\n\t\tEmail: "dev@stainless.com",\n\t\tRequest: "request",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'login email', + example: + "beeper-desktop-cli app:login email \\\n --access-token 'My Access Token' \\\n --email dev@stainless.com \\\n --request request", + }, + php: { + method: 'app->login->email', + example: + "app->login->email(\n email: 'dev@stainless.com', request: 'request'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/login/email \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "email": "dev@stainless.com",\n "request": "request"\n }\'', + }, + }, + }, + { + name: 'response', + endpoint: '/v1/app/login/response', + httpMethod: 'post', + summary: 'Complete login with code', + description: + 'Finish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.', + stainlessPath: '(resource) app.login > (method) response', + qualified: 'client.app.login.response', + params: ['request: string;', 'response: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }", + markdown: + "## response\n\n`client.app.login.response(request: string, response: string): { appState: object; desktopAPI: object; matrix: object; } | { copy: object; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n**post** `/v1/app/login/response`\n\nFinish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.\n\n### Parameters\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `response: string`\n Sign-in code from the user email.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.response', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);", + }, + python: { + method: 'app.login.response', + example: + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.response(\n request="request",\n response="response",\n)\nprint(response)', + }, + go: { + method: 'client.App.Login.Response', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Response(context.TODO(), beeperdesktopapi.AppLoginResponseParams{\n\t\tRequest: "request",\n\t\tResponse: "response",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'login response', + example: + "beeper-desktop-cli app:login response \\\n --access-token 'My Access Token' \\\n --request request \\\n --response response", + }, + php: { + method: 'app->login->response', + example: + "app->login->response(\n request: 'request', response: 'response'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/login/response \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "request": "request",\n "response": "response"\n }\'', + }, + }, + }, + { + name: 'register', + endpoint: '/v1/app/login/register', + httpMethod: 'post', + summary: 'Create account', + description: 'Create a Beeper account after the user chooses a username and accepts the Terms of Use.', + stainlessPath: '(resource) app.login > (method) register', + qualified: 'client.app.login.register', + params: ['acceptTerms: true;', 'leadToken: string;', 'request: string;', 'username: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; }", + markdown: + "## register\n\n`client.app.login.register(acceptTerms: true, leadToken: string, request: string, username: string): { appState: object; desktopAPI: object; matrix: object; }`\n\n**post** `/v1/app/login/register`\n\nCreate a Beeper account after the user chooses a username and accepts the Terms of Use.\n\n### Parameters\n\n- `acceptTerms: true`\n Confirms that the user accepted the Terms of Use and acknowledged the Privacy Policy.\n\n- `leadToken: string`\n Registration token returned by Beeper.\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `username: string`\n Username selected by the user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }`\n - `matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.register', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.login.register', + example: + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.register(\n accept_terms=True,\n lead_token="leadToken",\n request="request",\n username="x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.Login.Register', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Register(context.TODO(), beeperdesktopapi.AppLoginRegisterParams{\n\t\tAcceptTerms: true,\n\t\tLeadToken: "leadToken",\n\t\tRequest: "request",\n\t\tUsername: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'login register', + example: + "beeper-desktop-cli app:login register \\\n --access-token 'My Access Token' \\\n --accept-terms true \\\n --lead-token leadToken \\\n --request request \\\n --username x", + }, + php: { + method: 'app->login->register', + example: + "app->login->register(\n acceptTerms: true, leadToken: 'leadToken', request: 'request', username: 'x'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/login/register \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "acceptTerms": true,\n "leadToken": "leadToken",\n "request": "request",\n "username": "x"\n }\'', + }, + }, + }, + { + name: 'verify', + endpoint: '/v1/app/e2ee/recovery-code/verify', + httpMethod: 'post', + summary: 'Verify with recovery key', + description: 'Unlock encrypted messages with the user recovery key.', + stainlessPath: '(resource) app.e2ee.recovery_code > (method) verify', + qualified: 'client.app.e2ee.recoveryCode.verify', + params: ['recoveryCode: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## verify\n\n`client.app.e2ee.recoveryCode.verify(recoveryCode: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/verify`\n\nUnlock encrypted messages with the user recovery key.\n\n### Parameters\n\n- `recoveryCode: string`\n Recovery key saved by the user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.recoveryCode.verify', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' });\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.recovery_code.verify', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.verify(\n recovery_code="x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.RecoveryCode.Verify', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.Verify(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeVerifyParams{\n\t\tRecoveryCode: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'recovery_code verify', + example: + "beeper-desktop-cli app:e2ee:recovery-code verify \\\n --access-token 'My Access Token' \\\n --recovery-code x", + }, + php: { + method: 'app->e2ee->recoveryCode->verify', + example: + "app->e2ee->recoveryCode->verify(recoveryCode: 'x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/recovery-code/verify \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryCode": "x"\n }\'', + }, + }, + }, + { + name: 'mark_backed_up', + endpoint: '/v1/app/e2ee/recovery-code/mark-backed-up', + httpMethod: 'post', + summary: 'Mark recovery key as saved', + description: 'Record that the user saved their recovery key.', + stainlessPath: '(resource) app.e2ee.recovery_code > (method) mark_backed_up', + qualified: 'client.app.e2ee.recoveryCode.markBackedUp', + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## mark_backed_up\n\n`client.app.e2ee.recoveryCode.markBackedUp(): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/mark-backed-up`\n\nRecord that the user saved their recovery key.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.markBackedUp();\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.recoveryCode.markBackedUp', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.markBackedUp();\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.recovery_code.mark_backed_up', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.mark_backed_up()\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.RecoveryCode.MarkBackedUp', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.MarkBackedUp(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'recovery_code mark_backed_up', + example: + "beeper-desktop-cli app:e2ee:recovery-code mark-backed-up \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->e2ee->recoveryCode->markBackedUp', + example: + "app->e2ee->recoveryCode->markBackedUp();\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/recovery-code/mark-backed-up \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'create', + endpoint: '/v1/app/e2ee/recovery-code/reset', + httpMethod: 'post', + summary: 'Create new recovery key', + description: 'Create a new recovery key when the user cannot use the existing one.', + stainlessPath: '(resource) app.e2ee.recovery_code.reset > (method) create', + qualified: 'client.app.e2ee.recoveryCode.reset.create', + params: ['recoveryCode?: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; recoveryCode: string; }", + markdown: + "## create\n\n`client.app.e2ee.recoveryCode.reset.create(recoveryCode?: string): { appState: object; recoveryCode: string; }`\n\n**post** `/v1/app/e2ee/recovery-code/reset`\n\nCreate a new recovery key when the user cannot use the existing one.\n\n### Parameters\n\n- `recoveryCode?: string`\n Existing recovery key, if the user has it.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; recoveryCode: string; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `recoveryCode: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reset = await client.app.e2ee.recoveryCode.reset.create();\n\nconsole.log(reset);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.recoveryCode.reset.create', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reset = await client.app.e2ee.recoveryCode.reset.create();\n\nconsole.log(reset.appState);", + }, + python: { + method: 'app.e2ee.recovery_code.reset.create', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreset = client.app.e2ee.recovery_code.reset.create()\nprint(reset.app_state)', + }, + go: { + method: 'client.App.E2ee.RecoveryCode.Reset.New', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treset, err := client.App.E2ee.RecoveryCode.Reset.New(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeResetNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reset.AppState)\n}\n', + }, + cli: { + method: 'reset create', + example: + "beeper-desktop-cli app:e2ee:recovery-code:reset create \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->e2ee->recoveryCode->reset->create', + example: + "app->e2ee->recoveryCode->reset->create(\n recoveryCode: 'recoveryCode'\n);\n\nvar_dump($reset);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/recovery-code/reset \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'confirm', + endpoint: '/v1/app/e2ee/recovery-code/reset/confirm', + httpMethod: 'post', + summary: 'Confirm new recovery key', + description: 'Confirm that the new recovery key should be used for this account.', + stainlessPath: '(resource) app.e2ee.recovery_code.reset > (method) confirm', + qualified: 'client.app.e2ee.recoveryCode.reset.confirm', + params: ['recoveryCode: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## confirm\n\n`client.app.e2ee.recoveryCode.reset.confirm(recoveryCode: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/reset/confirm`\n\nConfirm that the new recovery key should be used for this account.\n\n### Parameters\n\n- `recoveryCode: string`\n New recovery key returned by the reset step.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.recoveryCode.reset.confirm', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' });\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.recovery_code.reset.confirm', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.reset.confirm(\n recovery_code="x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.RecoveryCode.Reset.Confirm', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.Reset.Confirm(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeResetConfirmParams{\n\t\tRecoveryCode: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'reset confirm', + example: + "beeper-desktop-cli app:e2ee:recovery-code:reset confirm \\\n --access-token 'My Access Token' \\\n --recovery-code x", + }, + php: { + method: 'app->e2ee->recoveryCode->reset->confirm', + example: + "app->e2ee->recoveryCode->reset->confirm(recoveryCode: 'x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/recovery-code/reset/confirm \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryCode": "x"\n }\'', + }, + }, + }, + { + name: 'create', + endpoint: '/v1/app/e2ee/verification', + httpMethod: 'post', + summary: 'Start device verification', + description: 'Start verifying this device from another signed-in device.', + stainlessPath: '(resource) app.e2ee.verification > (method) create', + qualified: 'client.app.e2ee.verification.create', + params: ['userID?: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; verificationID: string; }", + markdown: + "## create\n\n`client.app.e2ee.verification.create(userID?: string): { appState: object; verificationID: string; }`\n\n**post** `/v1/app/e2ee/verification`\n\nStart verifying this device from another signed-in device.\n\n### Parameters\n\n- `userID?: string`\n User ID to verify. Defaults to the signed-in user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; verificationID: string; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `verificationID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.e2ee.verification.create();\n\nconsole.log(verification);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.verification.create', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.e2ee.verification.create();\n\nconsole.log(verification.appState);", + }, + python: { + method: 'app.e2ee.verification.create', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.e2ee.verification.create()\nprint(verification.app_state)', + }, + go: { + method: 'client.App.E2ee.Verification.New', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.E2ee.Verification.New(context.TODO(), beeperdesktopapi.AppE2eeVerificationNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.AppState)\n}\n', + }, + cli: { + method: 'verification create', + example: "beeper-desktop-cli app:e2ee:verification create \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->e2ee->verification->create', + example: + "app->e2ee->verification->create(userID: 'userID');\n\nvar_dump($verification);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/verification \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'accept', + endpoint: '/v1/app/e2ee/verification/{verificationID}/accept', + httpMethod: 'post', + summary: 'Accept device verification', + description: 'Accept an incoming device verification request.', + stainlessPath: '(resource) app.e2ee.verification > (method) accept', + qualified: 'client.app.e2ee.verification.accept', + params: ['verificationID: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## accept\n\n`client.app.e2ee.verification.accept(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/accept`\n\nAccept an incoming device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.accept('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.verification.accept', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.accept('x');\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.verification.accept', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.accept(\n "x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.Verification.Accept', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Accept(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'verification accept', + example: + "beeper-desktop-cli app:e2ee:verification accept \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->e2ee->verification->accept', + example: + "app->e2ee->verification->accept('x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/accept \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'cancel', + endpoint: '/v1/app/e2ee/verification/{verificationID}/cancel', + httpMethod: 'post', + summary: 'Cancel device verification', + description: 'Cancel an active device verification request.', + stainlessPath: '(resource) app.e2ee.verification > (method) cancel', + qualified: 'client.app.e2ee.verification.cancel', + params: ['verificationID: string;', 'code?: string;', 'reason?: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## cancel\n\n`client.app.e2ee.verification.cancel(verificationID: string, code?: string, reason?: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/cancel`\n\nCancel an active device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n- `code?: string`\n Optional cancellation code.\n\n- `reason?: string`\n Optional user-facing cancellation reason.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.cancel('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.verification.cancel', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.cancel('x');\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.verification.cancel', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.cancel(\n verification_id="x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.Verification.Cancel', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Cancel(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.AppE2eeVerificationCancelParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'verification cancel', + example: + "beeper-desktop-cli app:e2ee:verification cancel \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->e2ee->verification->cancel', + example: + "app->e2ee->verification->cancel(\n 'x', code: 'code', reason: 'reason'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/cancel \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'scan', + endpoint: '/v1/app/e2ee/verification/qr/scan', + httpMethod: 'post', + summary: 'Scan verification QR code', + description: 'Submit the QR code scanned from another signed-in device.', + stainlessPath: '(resource) app.e2ee.verification.qr > (method) scan', + qualified: 'client.app.e2ee.verification.qr.scan', + params: ['data: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## scan\n\n`client.app.e2ee.verification.qr.scan(data: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/qr/scan`\n\nSubmit the QR code scanned from another signed-in device.\n\n### Parameters\n\n- `data: string`\n QR code payload scanned from the other device.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.qr.scan({ data: 'x' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.verification.qr.scan', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.qr.scan({ data: 'x' });\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.verification.qr.scan', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.qr.scan(\n data="x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.Verification.Qr.Scan', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Qr.Scan(context.TODO(), beeperdesktopapi.AppE2eeVerificationQrScanParams{\n\t\tData: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'qr scan', + example: + "beeper-desktop-cli app:e2ee:verification:qr scan \\\n --access-token 'My Access Token' \\\n --data x", + }, + php: { + method: 'app->e2ee->verification->qr->scan', + example: + "app->e2ee->verification->qr->scan(data: 'x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/verification/qr/scan \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "data": "x"\n }\'', + }, + }, + }, + { + name: 'confirm_scanned', + endpoint: '/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned', + httpMethod: 'post', + summary: 'Confirm QR code scan', + description: 'Confirm that another device scanned this device QR code.', + stainlessPath: '(resource) app.e2ee.verification.qr > (method) confirm_scanned', + qualified: 'client.app.e2ee.verification.qr.confirmScanned', + params: ['verificationID: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## confirm_scanned\n\n`client.app.e2ee.verification.qr.confirmScanned(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned`\n\nConfirm that another device scanned this device QR code.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.qr.confirmScanned('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.verification.qr.confirmScanned', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.qr.confirmScanned('x');\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.verification.qr.confirm_scanned', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.qr.confirm_scanned(\n "x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.Verification.Qr.ConfirmScanned', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Qr.ConfirmScanned(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'qr confirm_scanned', + example: + "beeper-desktop-cli app:e2ee:verification:qr confirm-scanned \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->e2ee->verification->qr->confirmScanned', + example: + "app->e2ee->verification->qr->confirmScanned('x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/qr/confirm-scanned \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'start', + endpoint: '/v1/app/e2ee/verification/{verificationID}/sas/start', + httpMethod: 'post', + summary: 'Start emoji verification', + description: 'Start emoji comparison for device verification.', + stainlessPath: '(resource) app.e2ee.verification.sas > (method) start', + qualified: 'client.app.e2ee.verification.sas.start', + params: ['verificationID: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## start\n\n`client.app.e2ee.verification.sas.start(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/sas/start`\n\nStart emoji comparison for device verification.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.sas.start('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.verification.sas.start', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.sas.start('x');\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.verification.sas.start', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.sas.start(\n "x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.Verification.Sas.Start', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Sas.Start(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'sas start', + example: + "beeper-desktop-cli app:e2ee:verification:sas start \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->e2ee->verification->sas->start', + example: + "app->e2ee->verification->sas->start('x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/sas/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'confirm', + endpoint: '/v1/app/e2ee/verification/{verificationID}/sas/confirm', + httpMethod: 'post', + summary: 'Confirm emoji verification', + description: 'Confirm that the emoji or number sequence matches on both devices.', + stainlessPath: '(resource) app.e2ee.verification.sas > (method) confirm', + qualified: 'client.app.e2ee.verification.sas.confirm', + params: ['verificationID: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + markdown: + "## confirm\n\n`client.app.e2ee.verification.sas.confirm(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/sas/confirm`\n\nConfirm that the emoji or number sequence matches on both devices.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.sas.confirm('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.e2ee.verification.sas.confirm', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.sas.confirm('x');\n\nconsole.log(response.appState);", + }, + python: { + method: 'app.e2ee.verification.sas.confirm', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.sas.confirm(\n "x",\n)\nprint(response.app_state)', + }, + go: { + method: 'client.App.E2ee.Verification.Sas.Confirm', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Sas.Confirm(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + }, + cli: { + method: 'sas confirm', + example: + "beeper-desktop-cli app:e2ee:verification:sas confirm \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->e2ee->verification->sas->confirm', + example: + "app->e2ee->verification->sas->confirm('x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/sas/confirm \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'list', + endpoint: '/v1/accounts', + httpMethod: 'get', + summary: 'List Chat Accounts', + description: + 'List Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.', + stainlessPath: '(resource) accounts > (method) list', + qualified: 'client.accounts.list', + response: + "{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]", + markdown: + "## list\n\n`client.accounts.list(): object[]`\n\n**get** `/v1/accounts`\n\nList Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.\n\n### Returns\n\n- `{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]`\n Accounts configured on this device. Includes accountID, bridge metadata, optional network name, and user identity.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);\n```", + perLanguage: { + typescript: { + method: 'client.accounts.list', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);", + }, + python: { + method: 'accounts.list', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccounts = client.accounts.list()\nprint(accounts)', + }, + go: { + method: 'client.Accounts.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccounts, err := client.Accounts.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accounts)\n}\n', + }, + cli: { + method: 'accounts list', + example: "beeper-desktop-cli accounts list \\\n --access-token 'My Access Token'", + }, + php: { + method: 'accounts->list', + example: + "accounts->list();\n\nvar_dump($accounts);", + }, + http: { + example: + 'curl http://localhost:23373/v1/accounts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'search', + endpoint: '/v1/accounts/{accountID}/contacts', + httpMethod: 'get', + summary: 'Search contacts', + description: + 'Search contacts on a specific account using merged account contacts, network search, and exact identifier lookup.', + stainlessPath: '(resource) accounts.contacts > (method) search', + qualified: 'client.accounts.contacts.search', + params: ['accountID: string;', 'query: string;'], + response: + '{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }', + markdown: + "## search\n\n`client.accounts.contacts.search(accountID: string, query: string): { items: user[]; }`\n\n**get** `/v1/accounts/{accountID}/contacts`\n\nSearch contacts on a specific account using merged account contacts, network search, and exact identifier lookup.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `query: string`\n Text to search users by. Network-specific behavior.\n\n### Returns\n\n- `{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }`\n\n - `items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.accounts.contacts.search', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response.items);", + }, + python: { + method: 'accounts.contacts.search', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.accounts.contacts.search(\n account_id="accountID",\n query="x",\n)\nprint(response.items)', + }, + go: { + method: 'client.Accounts.Contacts.Search', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Accounts.Contacts.Search(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactSearchParams{\n\t\t\tQuery: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Items)\n}\n', + }, + cli: { + method: 'contacts search', + example: + "beeper-desktop-cli accounts:contacts search \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --query x", + }, + php: { + method: 'accounts->contacts->search', + example: + "accounts->contacts->search('accountID', query: 'x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID/contacts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'list', + endpoint: '/v1/accounts/{accountID}/contacts/list', + httpMethod: 'get', + summary: 'List contacts', + description: 'List merged contacts for a specific account with cursor-based pagination.', + stainlessPath: '(resource) accounts.contacts > (method) list', + qualified: 'client.accounts.contacts.list', + params: [ + 'accountID: string;', + 'cursor?: string;', + "direction?: 'after' | 'before';", + 'limit?: number;', + 'query?: string;', + ], + response: + '{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }', + markdown: + "## list\n\n`client.accounts.contacts.list(accountID: string, cursor?: string, direction?: 'after' | 'before', limit?: number, query?: string): { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n\n**get** `/v1/accounts/{accountID}/contacts/list`\n\nList merged contacts for a specific account with cursor-based pagination.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `limit?: number`\n Maximum contacts to return per page.\n\n- `query?: string`\n Optional search query for blended contact lookup.\n\n### Returns\n\n- `{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n User the account belongs to.\n\n - `id: string`\n - `cannotMessage?: boolean`\n - `email?: string`\n - `fullName?: string`\n - `imgURL?: string`\n - `isSelf?: boolean`\n - `phoneNumber?: string`\n - `username?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user);\n}\n```", + perLanguage: { + typescript: { + method: 'client.accounts.contacts.list', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user.id);\n}", + }, + python: { + method: 'accounts.contacts.list', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.accounts.contacts.list(\n account_id="accountID",\n)\npage = page.items[0]\nprint(page.id)', + }, + go: { + method: 'client.Accounts.Contacts.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Accounts.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + }, + cli: { + method: 'contacts list', + example: + "beeper-desktop-cli accounts:contacts list \\\n --access-token 'My Access Token' \\\n --account-id accountID", + }, + php: { + method: 'accounts->contacts->list', + example: + "accounts->contacts->list(\n 'accountID',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n limit: 1,\n query: 'x',\n);\n\nvar_dump($page);", + }, + http: { + example: + 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID/contacts/list \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'list', + endpoint: '/v1/bridges', + httpMethod: 'get', + summary: 'List bridges', + description: + 'List bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.', + stainlessPath: '(resource) bridges > (method) list', + qualified: 'client.bridges.list', + response: + "{ items: { accounts: account[]; activeAccountCount: number; bridge: object; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]; }", + markdown: + "## list\n\n`client.bridges.list(): { items: bridge_availability[]; }`\n\n**get** `/v1/bridges`\n\nList bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.\n\n### Returns\n\n- `{ items: { accounts: account[]; activeAccountCount: number; bridge: object; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]; }`\n Bridge-backed account types and their connected accounts.\n\n - `items: { accounts: { accountID: string; bridge: object; user: user; network?: string; }[]; activeAccountCount: number; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges);\n```", + perLanguage: { + typescript: { + method: 'client.bridges.list', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges.items);", + }, + python: { + method: 'bridges.list', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nbridges = client.bridges.list()\nprint(bridges.items)', + }, + go: { + method: 'client.Bridges.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tbridges, err := client.Bridges.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", bridges.Items)\n}\n', + }, + cli: { + method: 'bridges list', + example: "beeper-desktop-cli bridges list \\\n --access-token 'My Access Token'", + }, + php: { + method: 'bridges->list', + example: + "bridges->list();\n\nvar_dump($bridges);", + }, + http: { + example: + 'curl http://localhost:23373/v1/bridges \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'retrieve_profile', + endpoint: '/_matrix/client/v3/profile/{userId}', + httpMethod: 'get', + summary: 'Get all profile information for a user.', + description: 'Get the complete profile for a user.', + stainlessPath: '(resource) matrix.users > (method) retrieve_profile', + qualified: 'client.matrix.users.retrieveProfile', + params: ['userId: string;'], + response: '{ avatar_url?: string; displayname?: string; m.tz?: string; }', + markdown: + "## retrieve_profile\n\n`client.matrix.users.retrieveProfile(userId: string): { avatar_url?: string; displayname?: string; m.tz?: string; }`\n\n**get** `/_matrix/client/v3/profile/{userId}`\n\nGet the complete profile for a user.\n\n### Parameters\n\n- `userId: string`\n\n### Returns\n\n- `{ avatar_url?: string; displayname?: string; m.tz?: string; }`\n\n - `avatar_url?: string`\n - `displayname?: string`\n - `m.tz?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.users.retrieveProfile('@alice:example.com');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.users.retrieveProfile', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.users.retrieveProfile('@alice:example.com');\n\nconsole.log(response.avatar_url);", + }, + python: { + method: 'matrix.users.retrieve_profile', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.users.retrieve_profile(\n "@alice:example.com",\n)\nprint(response.avatar_url)', + }, + go: { + method: 'client.Matrix.Users.GetProfile', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Users.GetProfile(context.TODO(), "@alice:example.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AvatarURL)\n}\n', + }, + cli: { + method: 'users retrieve_profile', + example: + "beeper-desktop-cli matrix:users retrieve-profile \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com", + }, + php: { + method: 'matrix->users->retrieveProfile', + example: + "matrix->users->retrieveProfile('@alice:example.com');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/profile/$USER_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'retrieve', + endpoint: '/_matrix/client/v3/user/{userId}/account_data/{type}', + httpMethod: 'get', + summary: 'Get some account data for the user.', + description: + 'Get some account data for the client. This config is only visible to the user\nthat set the account data.', + stainlessPath: '(resource) matrix.users.account_data > (method) retrieve', + qualified: 'client.matrix.users.accountData.retrieve', + params: ['userId: string;', 'type: string;'], + response: 'object', + markdown: + "## retrieve\n\n`client.matrix.users.accountData.retrieve(userId: string, type: string): object`\n\n**get** `/_matrix/client/v3/user/{userId}/account_data/{type}`\n\nGet some account data for the client. This config is only visible to the user\nthat set the account data.\n\n### Parameters\n\n- `userId: string`\n\n- `type: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.users.accountData.retrieve('org.example.custom.config', { userId: '@alice:example.com' });\n\nconsole.log(accountData);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.users.accountData.retrieve', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.users.accountData.retrieve('org.example.custom.config', {\n userId: '@alice:example.com',\n});\n\nconsole.log(accountData);", + }, + python: { + method: 'matrix.users.account_data.retrieve', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.users.account_data.retrieve(\n type="org.example.custom.config",\n user_id="@alice:example.com",\n)\nprint(account_data)', + }, + go: { + method: 'client.Matrix.Users.AccountData.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Users.AccountData.Get(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.config",\n\t\tbeeperdesktopapi.MatrixUserAccountDataGetParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + }, + cli: { + method: 'account_data retrieve', + example: + "beeper-desktop-cli matrix:users:account-data retrieve \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --type org.example.custom.config", + }, + php: { + method: 'matrix->users->accountData->retrieve', + example: + "matrix->users->accountData->retrieve(\n 'org.example.custom.config', userID: '@alice:example.com'\n);\n\nvar_dump($accountData);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/account_data/$TYPE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'update', + endpoint: '/_matrix/client/v3/user/{userId}/account_data/{type}', + httpMethod: 'put', + summary: 'Set some account data for the user.', + description: + 'Set some account data for the client. This config is only visible to the user\nthat set the account data. The config will be available to clients through the\ntop-level `account_data` field in the homeserver response to\n[/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).', + stainlessPath: '(resource) matrix.users.account_data > (method) update', + qualified: 'client.matrix.users.accountData.update', + params: ['userId: string;', 'type: string;', 'body: object;'], + response: 'object', + markdown: + "## update\n\n`client.matrix.users.accountData.update(userId: string, type: string, body: object): object`\n\n**put** `/_matrix/client/v3/user/{userId}/account_data/{type}`\n\nSet some account data for the client. This config is only visible to the user\nthat set the account data. The config will be available to clients through the\ntop-level `account_data` field in the homeserver response to\n[/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).\n\n### Parameters\n\n- `userId: string`\n\n- `type: string`\n\n- `body: object`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.users.accountData.update('org.example.custom.config', {\n userId: '@alice:example.com',\n body: { custom_account_data_key: 'custom_config_value' },\n});\n\nconsole.log(accountData);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.users.accountData.update', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.users.accountData.update('org.example.custom.config', {\n userId: '@alice:example.com',\n body: { custom_account_data_key: 'custom_config_value' },\n});\n\nconsole.log(accountData);", + }, + python: { + method: 'matrix.users.account_data.update', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.users.account_data.update(\n type="org.example.custom.config",\n user_id="@alice:example.com",\n body={\n "custom_account_data_key": "custom_config_value"\n },\n)\nprint(account_data)', + }, + go: { + method: 'client.Matrix.Users.AccountData.Update', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Users.AccountData.Update(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.config",\n\t\tbeeperdesktopapi.MatrixUserAccountDataUpdateParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tBody: map[string]any{\n\t\t\t\t"custom_account_data_key": "custom_config_value",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + }, + cli: { + method: 'account_data update', + example: + "beeper-desktop-cli matrix:users:account-data update \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --type org.example.custom.config \\\n --body '{custom_account_data_key: custom_config_value}'", + }, + php: { + method: 'matrix->users->accountData->update', + example: + "matrix->users->accountData->update(\n 'org.example.custom.config',\n userID: '@alice:example.com',\n body: ['custom_account_data_key' => 'custom_config_value'],\n);\n\nvar_dump($accountData);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/account_data/$TYPE \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "custom_account_data_key": "custom_config_value"\n }\'', + }, + }, + }, + { + name: 'create', + endpoint: '/_matrix/client/v3/createRoom', + httpMethod: 'post', + summary: 'Create a new room', + description: + "Create a new room with various configuration options.\n\nThe server MUST apply the normal state resolution rules when creating\nthe new room, including checking power levels for each event. It MUST\napply the events implied by the request in the following order:\n\n1. The `m.room.create` event itself. Must be the first event in the\n room.\n\n2. An `m.room.member` event for the creator to join the room. This is\n needed so the remaining events can be sent.\n\n3. A default `m.room.power_levels` event. Overridden by the\n `power_level_content_override` parameter.\n\n In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the room creator (and not\n other members) will be given permission to send state events.\n\n In room versions 12 and later, the room creator is given infinite\n power level and cannot be specified in the `users` field of\n `m.room.power_levels`, so is not listed explicitly.\n\n **Note**: For `trusted_private_chat`, the users specified in the\n `invite` parameter SHOULD also be appended to `additional_creators`\n by the server, per the `creation_content` parameter.\n\n If the room's version is 12 or higher, the power level for sending\n `m.room.tombstone` events MUST explicitly be higher than `state_default`.\n For example, set to 150 instead of 100.\n\n4. An `m.room.canonical_alias` event if `room_alias_name` is given.\n\n5. Events set by the `preset`. Currently these are the `m.room.join_rules`,\n `m.room.history_visibility`, and `m.room.guest_access` state events.\n\n6. Events listed in `initial_state`, in the order that they are\n listed.\n\n7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`\n state events).\n\n8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with\n `membership: invite` and `m.room.third_party_invite`).\n\nThe available presets do the following with respect to room state:\n\n| Preset | `join_rules` | `history_visibility` | `guest_access` | Other |\n|------------------------|--------------|----------------------|----------------|-------|\n| `private_chat` | `invite` | `shared` | `can_join` | |\n| `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. |\n| `public_chat` | `public` | `shared` | `forbidden` | |\n\nThe server will create a `m.room.create` event in the room with the\nrequesting user as the creator, alongside other keys provided in the\n`creation_content` or implied by behaviour of `creation_content`.", + stainlessPath: '(resource) matrix.rooms > (method) create', + qualified: 'client.matrix.rooms.create', + params: [ + 'creation_content?: object;', + 'initial_state?: { content: object; type: string; state_key?: string; }[];', + 'invite?: string[];', + 'invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[];', + 'is_direct?: boolean;', + 'name?: string;', + 'power_level_content_override?: object;', + "preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat';", + 'room_alias_name?: string;', + 'room_version?: string;', + 'topic?: string;', + "visibility?: 'public' | 'private';", + ], + response: '{ room_id: string; }', + markdown: + "## create\n\n`client.matrix.rooms.create(creation_content?: object, initial_state?: { content: object; type: string; state_key?: string; }[], invite?: string[], invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[], is_direct?: boolean, name?: string, power_level_content_override?: object, preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat', room_alias_name?: string, room_version?: string, topic?: string, visibility?: 'public' | 'private'): { room_id: string; }`\n\n**post** `/_matrix/client/v3/createRoom`\n\nCreate a new room with various configuration options.\n\nThe server MUST apply the normal state resolution rules when creating\nthe new room, including checking power levels for each event. It MUST\napply the events implied by the request in the following order:\n\n1. The `m.room.create` event itself. Must be the first event in the\n room.\n\n2. An `m.room.member` event for the creator to join the room. This is\n needed so the remaining events can be sent.\n\n3. A default `m.room.power_levels` event. Overridden by the\n `power_level_content_override` parameter.\n\n In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the room creator (and not\n other members) will be given permission to send state events.\n\n In room versions 12 and later, the room creator is given infinite\n power level and cannot be specified in the `users` field of\n `m.room.power_levels`, so is not listed explicitly.\n\n **Note**: For `trusted_private_chat`, the users specified in the\n `invite` parameter SHOULD also be appended to `additional_creators`\n by the server, per the `creation_content` parameter.\n\n If the room's version is 12 or higher, the power level for sending\n `m.room.tombstone` events MUST explicitly be higher than `state_default`.\n For example, set to 150 instead of 100.\n\n4. An `m.room.canonical_alias` event if `room_alias_name` is given.\n\n5. Events set by the `preset`. Currently these are the `m.room.join_rules`,\n `m.room.history_visibility`, and `m.room.guest_access` state events.\n\n6. Events listed in `initial_state`, in the order that they are\n listed.\n\n7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`\n state events).\n\n8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with\n `membership: invite` and `m.room.third_party_invite`).\n\nThe available presets do the following with respect to room state:\n\n| Preset | `join_rules` | `history_visibility` | `guest_access` | Other |\n|------------------------|--------------|----------------------|----------------|-------|\n| `private_chat` | `invite` | `shared` | `can_join` | |\n| `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. |\n| `public_chat` | `public` | `shared` | `forbidden` | |\n\nThe server will create a `m.room.create` event in the room with the\nrequesting user as the creator, alongside other keys provided in the\n`creation_content` or implied by behaviour of `creation_content`.\n\n### Parameters\n\n- `creation_content?: object`\n Extra keys, such as `m.federate`, to be added to the content\nof the [`m.room.create`](https://spec.matrix.org/v1.18/client-server-api/#mroomcreate) event.\n\nThe server will overwrite the following\nkeys: `creator`, `room_version`. Future versions of the specification\nmay allow the server to overwrite other keys.\n\nWhen using the `trusted_private_chat` preset, the server SHOULD combine\n`additional_creators` specified here and the `invite` array into the\neventual `m.room.create` event's `additional_creators`, deduplicating\nbetween the two parameters.\n\n- `initial_state?: { content: object; type: string; state_key?: string; }[]`\n A list of state events to set in the new room. This allows\nthe user to override the default state events set in the new\nroom. The expected format of the state events are an object\nwith type, state_key and content keys set.\n\nTakes precedence over events set by `preset`, but gets\noverridden by `name` and `topic` keys.\n\n- `invite?: string[]`\n A list of user IDs to invite to the room. This will tell the\nserver to invite everyone in the list to the newly created room.\n\n- `invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[]`\n A list of objects representing third-party IDs to invite into\nthe room.\n\n- `is_direct?: boolean`\n This flag makes the server set the `is_direct` flag on the\n`m.room.member` events sent to the users in `invite` and\n`invite_3pid`. See [Direct Messaging](https://spec.matrix.org/v1.18/client-server-api/#direct-messaging) for more information.\n\n- `name?: string`\n If this is included, an [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname) event\nwill be sent into the room to indicate the name for the room.\nThis overwrites any [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname)\nevent in `initial_state`.\n\n- `power_level_content_override?: object`\n The power level content to override in the default power level\nevent. This object is applied on top of the generated\n[`m.room.power_levels`](https://spec.matrix.org/v1.18/client-server-api/#mroompower_levels)\nevent content prior to it being sent to the room. Defaults to\noverriding nothing.\n\n- `preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat'`\n Convenience parameter for setting various default state events\nbased on a preset.\n\nIf unspecified, the server should use the `visibility` to determine\nwhich preset to use. A visibility of `public` equates to a preset of\n`public_chat` and `private` visibility equates to a preset of\n`private_chat`.\n\n- `room_alias_name?: string`\n The desired room alias **local part**. If this is included, a\nroom alias will be created and mapped to the newly created\nroom. The alias will belong on the *same* homeserver which\ncreated the room. For example, if this was set to \"foo\" and\nsent to the homeserver \"example.com\" the complete room alias\nwould be `#foo:example.com`.\n\nThe complete room alias will become the canonical alias for\nthe room and an `m.room.canonical_alias` event will be sent\ninto the room.\n\n- `room_version?: string`\n The room version to set for the room. If not provided, the homeserver is\nto use its configured default. If provided, the homeserver will return a\n400 error with the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not\nsupport the room version.\n\n- `topic?: string`\n If this is included, an [`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic)\nevent with a `text/plain` mimetype will be sent into the room\nto indicate the topic for the room. This overwrites any\n[`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic) event in `initial_state`.\n\n- `visibility?: 'public' | 'private'`\n The room's visibility in the server's\n[published room directory](https://spec.matrix.org/v1.18/client-server-api#published-room-directory).\nDefaults to `private`.\n\n### Returns\n\n- `{ room_id: string; }`\n Information about the newly created room.\n\n - `room_id: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst room = await client.matrix.rooms.create();\n\nconsole.log(room);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.rooms.create', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst room = await client.matrix.rooms.create();\n\nconsole.log(room.room_id);", + }, + python: { + method: 'matrix.rooms.create', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nroom = client.matrix.rooms.create()\nprint(room.room_id)', + }, + go: { + method: 'client.Matrix.Rooms.New', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\troom, err := client.Matrix.Rooms.New(context.TODO(), beeperdesktopapi.MatrixRoomNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", room.RoomID)\n}\n', + }, + cli: { + method: 'rooms create', + example: "beeper-desktop-cli matrix:rooms create \\\n --access-token 'My Access Token'", + }, + php: { + method: 'matrix->rooms->create', + example: + "matrix->rooms->create(\n creationContent: ['m.federate' => false],\n initialState: [\n ['content' => (object) [], 'type' => 'type', 'stateKey' => 'state_key']\n ],\n invite: ['string'],\n invite3pid: [\n [\n 'address' => 'cheeky@monkey.com',\n 'idAccessToken' => 'abc123_OpaqueString',\n 'idServer' => 'matrix.org',\n 'medium' => 'email',\n ],\n ],\n isDirect: true,\n name: 'The Grand Duke Pub',\n powerLevelContentOverride: (object) [],\n preset: 'public_chat',\n roomAliasName: 'thepub',\n roomVersion: '1',\n topic: 'All about happy hour',\n visibility: 'public',\n);\n\nvar_dump($room);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/createRoom \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "creation_content": {\n "m.federate": false\n },\n "name": "The Grand Duke Pub",\n "preset": "public_chat",\n "room_alias_name": "thepub",\n "room_version": "1",\n "topic": "All about happy hour"\n }\'', + }, + }, + }, + { + name: 'join', + endpoint: '/_matrix/client/v3/join/{roomIdOrAlias}', + httpMethod: 'post', + summary: 'Join the requesting user to a particular room.', + description: + "*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.\n\nThis API starts a user's participation in a particular room, if that user\nis allowed to participate in that room. After this call, the client is\nallowed to see all current state events in the room, and all subsequent\nevents associated with the room until the user leaves the room.\n\nAfter a user has joined a room, the room will appear as an entry in the\nresponse of the [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync)\nand [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) APIs.", + stainlessPath: '(resource) matrix.rooms > (method) join', + qualified: 'client.matrix.rooms.join', + params: [ + 'roomIdOrAlias: string;', + 'via?: string[];', + 'reason?: string;', + 'third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; };', + ], + response: '{ room_id: string; }', + markdown: + "## join\n\n`client.matrix.rooms.join(roomIdOrAlias: string, via?: string[], reason?: string, third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; }): { room_id: string; }`\n\n**post** `/_matrix/client/v3/join/{roomIdOrAlias}`\n\n*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.\n\nThis API starts a user's participation in a particular room, if that user\nis allowed to participate in that room. After this call, the client is\nallowed to see all current state events in the room, and all subsequent\nevents associated with the room until the user leaves the room.\n\nAfter a user has joined a room, the room will appear as an entry in the\nresponse of the [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync)\nand [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) APIs.\n\n### Parameters\n\n- `roomIdOrAlias: string`\n\n- `via?: string[]`\n The servers to attempt to join the room through. One of the servers\nmust be participating in the room.\n\n- `reason?: string`\n Optional reason to be included as the `reason` on the subsequent\nmembership event.\n\n- `third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; }`\n A signature of an `m.third_party_invite` token to prove that this user\nowns a third-party identity which has been invited to the room.\n - `token: string`\n The state key of the m.third_party_invite event.\n - `mxid: string`\n The Matrix ID of the invitee.\n - `sender: string`\n The Matrix ID of the user who issued the invite.\n - `signatures: object`\n A signatures object containing a signature of the entire signed object.\n\n### Returns\n\n- `{ room_id: string; }`\n\n - `room_id: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.rooms.join('!monkeys:matrix.org');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.rooms.join', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.rooms.join('!monkeys:matrix.org');\n\nconsole.log(response.room_id);", + }, + python: { + method: 'matrix.rooms.join', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.rooms.join(\n room_id_or_alias="!monkeys:matrix.org",\n)\nprint(response.room_id)', + }, + go: { + method: 'client.Matrix.Rooms.Join', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Rooms.Join(\n\t\tcontext.TODO(),\n\t\t"!monkeys:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomJoinParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.RoomID)\n}\n', + }, + cli: { + method: 'rooms join', + example: + "beeper-desktop-cli matrix:rooms join \\\n --access-token 'My Access Token' \\\n --room-id-or-alias '!monkeys:matrix.org'", + }, + php: { + method: 'matrix->rooms->join', + example: + "matrix->rooms->join(\n '!monkeys:matrix.org',\n via: ['string'],\n reason: 'Looking for support',\n thirdPartySigned: [\n 'token' => 'random8nonce',\n 'mxid' => 'bob',\n 'sender' => 'alice',\n 'signatures' => ['example.org' => ['ed25519:0' => 'some9signature']],\n ],\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/join/$ROOM_ID_OR_ALIAS \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reason": "Looking for support"\n }\'', + }, + }, + }, + { + name: 'leave', + endpoint: '/_matrix/client/v3/rooms/{roomId}/leave', + httpMethod: 'post', + summary: 'Stop the requesting user participating in a particular room.', + description: + "This API stops a user participating in a particular room.\n\nIf the user was already in the room, they will no longer be able to see\nnew events in the room. If the room requires an invite to join, they\nwill need to be re-invited before they can re-join.\n\nIf the user was invited to the room, but had not joined, this call\nserves to reject the invite.\n\nServers MAY additionally forget the room when this endpoint is called –\njust as if the user had also invoked [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget).\nServers that do this, MUST inform clients about this behavior using the\n[`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability)\ncapability.\n\nIf the server doesn't automatically forget the room, the user will still be\nallowed to retrieve history from the room which they were previously allowed\nto see.", + stainlessPath: '(resource) matrix.rooms > (method) leave', + qualified: 'client.matrix.rooms.leave', + params: ['roomId: string;', 'reason?: string;'], + response: 'object', + markdown: + "## leave\n\n`client.matrix.rooms.leave(roomId: string, reason?: string): object`\n\n**post** `/_matrix/client/v3/rooms/{roomId}/leave`\n\nThis API stops a user participating in a particular room.\n\nIf the user was already in the room, they will no longer be able to see\nnew events in the room. If the room requires an invite to join, they\nwill need to be re-invited before they can re-join.\n\nIf the user was invited to the room, but had not joined, this call\nserves to reject the invite.\n\nServers MAY additionally forget the room when this endpoint is called –\njust as if the user had also invoked [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget).\nServers that do this, MUST inform clients about this behavior using the\n[`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability)\ncapability.\n\nIf the server doesn't automatically forget the room, the user will still be\nallowed to retrieve history from the room which they were previously allowed\nto see.\n\n### Parameters\n\n- `roomId: string`\n\n- `reason?: string`\n Optional reason to be included as the `reason` on the subsequent\nmembership event.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.rooms.leave('!nkl290a:matrix.org');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.rooms.leave', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.rooms.leave('!nkl290a:matrix.org');\n\nconsole.log(response);", + }, + python: { + method: 'matrix.rooms.leave', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.rooms.leave(\n room_id="!nkl290a:matrix.org",\n)\nprint(response)', + }, + go: { + method: 'client.Matrix.Rooms.Leave', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Rooms.Leave(\n\t\tcontext.TODO(),\n\t\t"!nkl290a:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomLeaveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'rooms leave', + example: + "beeper-desktop-cli matrix:rooms leave \\\n --access-token 'My Access Token' \\\n --room-id '!nkl290a:matrix.org'", + }, + php: { + method: 'matrix->rooms->leave', + example: + "matrix->rooms->leave(\n '!nkl290a:matrix.org', reason: 'Saying farewell - thanks for the support!'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/leave \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reason": "Saying farewell - thanks for the support!"\n }\'', + }, + }, + }, + { + name: 'retrieve', + endpoint: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', + httpMethod: 'get', + summary: 'Get some account data for the user that is specific to a room.', + description: + 'Get some account data for the client on a given room. This config is only\nvisible to the user that set the account data.', + stainlessPath: '(resource) matrix.rooms.account_data > (method) retrieve', + qualified: 'client.matrix.rooms.accountData.retrieve', + params: ['userId: string;', 'roomId: string;', 'type: string;'], + response: 'object', + markdown: + "## retrieve\n\n`client.matrix.rooms.accountData.retrieve(userId: string, roomId: string, type: string): object`\n\n**get** `/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}`\n\nGet some account data for the client on a given room. This config is only\nvisible to the user that set the account data.\n\n### Parameters\n\n- `userId: string`\n\n- `roomId: string`\n\n- `type: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.rooms.accountData.retrieve('org.example.custom.room.config', { userId: '@alice:example.com', roomId: '!726s6s6q:example.com' });\n\nconsole.log(accountData);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.rooms.accountData.retrieve', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.rooms.accountData.retrieve(\n 'org.example.custom.room.config',\n { userId: '@alice:example.com', roomId: '!726s6s6q:example.com' },\n);\n\nconsole.log(accountData);", + }, + python: { + method: 'matrix.rooms.account_data.retrieve', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.rooms.account_data.retrieve(\n type="org.example.custom.room.config",\n user_id="@alice:example.com",\n room_id="!726s6s6q:example.com",\n)\nprint(account_data)', + }, + go: { + method: 'client.Matrix.Rooms.AccountData.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Rooms.AccountData.Get(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.room.config",\n\t\tbeeperdesktopapi.MatrixRoomAccountDataGetParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tRoomID: "!726s6s6q:example.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + }, + cli: { + method: 'account_data retrieve', + example: + "beeper-desktop-cli matrix:rooms:account-data retrieve \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --room-id '!726s6s6q:example.com' \\\n --type org.example.custom.room.config", + }, + php: { + method: 'matrix->rooms->accountData->retrieve', + example: + "matrix->rooms->accountData->retrieve(\n 'org.example.custom.room.config',\n userID: '@alice:example.com',\n roomID: '!726s6s6q:example.com',\n);\n\nvar_dump($accountData);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/rooms/$ROOM_ID/account_data/$TYPE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'update', + endpoint: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', + httpMethod: 'put', + summary: 'Set some account data for the user that is specific to a room.', + description: + 'Set some account data for the client on a given room. This config is only\nvisible to the user that set the account data. The config will be delivered to\nclients in the per-room entries via [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).', + stainlessPath: '(resource) matrix.rooms.account_data > (method) update', + qualified: 'client.matrix.rooms.accountData.update', + params: ['userId: string;', 'roomId: string;', 'type: string;', 'body: object;'], + response: 'object', + markdown: + "## update\n\n`client.matrix.rooms.accountData.update(userId: string, roomId: string, type: string, body: object): object`\n\n**put** `/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}`\n\nSet some account data for the client on a given room. This config is only\nvisible to the user that set the account data. The config will be delivered to\nclients in the per-room entries via [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).\n\n### Parameters\n\n- `userId: string`\n\n- `roomId: string`\n\n- `type: string`\n\n- `body: object`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.rooms.accountData.update('org.example.custom.room.config', {\n userId: '@alice:example.com',\n roomId: '!726s6s6q:example.com',\n body: { custom_account_data_key: 'custom_account_data_value' },\n});\n\nconsole.log(accountData);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.rooms.accountData.update', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.rooms.accountData.update('org.example.custom.room.config', {\n userId: '@alice:example.com',\n roomId: '!726s6s6q:example.com',\n body: { custom_account_data_key: 'custom_account_data_value' },\n});\n\nconsole.log(accountData);", + }, + python: { + method: 'matrix.rooms.account_data.update', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.rooms.account_data.update(\n type="org.example.custom.room.config",\n user_id="@alice:example.com",\n room_id="!726s6s6q:example.com",\n body={\n "custom_account_data_key": "custom_account_data_value"\n },\n)\nprint(account_data)', + }, + go: { + method: 'client.Matrix.Rooms.AccountData.Update', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Rooms.AccountData.Update(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.room.config",\n\t\tbeeperdesktopapi.MatrixRoomAccountDataUpdateParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tRoomID: "!726s6s6q:example.com",\n\t\t\tBody: map[string]any{\n\t\t\t\t"custom_account_data_key": "custom_account_data_value",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + }, + cli: { + method: 'account_data update', + example: + "beeper-desktop-cli matrix:rooms:account-data update \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --room-id '!726s6s6q:example.com' \\\n --type org.example.custom.room.config \\\n --body '{custom_account_data_key: custom_account_data_value}'", + }, + php: { + method: 'matrix->rooms->accountData->update', + example: + "matrix->rooms->accountData->update(\n 'org.example.custom.room.config',\n userID: '@alice:example.com',\n roomID: '!726s6s6q:example.com',\n body: ['custom_account_data_key' => 'custom_account_data_value'],\n);\n\nvar_dump($accountData);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/rooms/$ROOM_ID/account_data/$TYPE \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "custom_account_data_key": "custom_account_data_value"\n }\'', + }, + }, + }, + { + name: 'list', + endpoint: '/_matrix/client/v3/rooms/{roomId}/state', + httpMethod: 'get', + summary: 'Get all state events in the current state of a room.', + description: 'Get the state events for the current state of a room.', + stainlessPath: '(resource) matrix.rooms.state > (method) list', + qualified: 'client.matrix.rooms.state.list', + params: ['roomId: string;'], + response: + '{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }[]', + markdown: + "## list\n\n`client.matrix.rooms.state.list(roomId: string): { content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: object; }[]`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/state`\n\nGet the state events for the current state of a room.\n\n### Parameters\n\n- `roomId: string`\n\n### Returns\n\n- `{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }[]`\n If the user is a member of the room this will be the\ncurrent state of the room as a list of events. If the user\nhas left the room then this will be the state of the room\nwhen they left as a list of events.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst states = await client.matrix.rooms.state.list('!636q39766251:example.com');\n\nconsole.log(states);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.rooms.state.list', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst states = await client.matrix.rooms.state.list('!636q39766251:example.com');\n\nconsole.log(states);", + }, + python: { + method: 'matrix.rooms.state.list', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nstates = client.matrix.rooms.state.list(\n "!636q39766251:example.com",\n)\nprint(states)', + }, + go: { + method: 'client.Matrix.Rooms.State.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tstates, err := client.Matrix.Rooms.State.List(context.TODO(), "!636q39766251:example.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", states)\n}\n', + }, + cli: { + method: 'state list', + example: + "beeper-desktop-cli matrix:rooms:state list \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:example.com'", + }, + php: { + method: 'matrix->rooms->state->list', + example: + "matrix->rooms->state->list('!636q39766251:example.com');\n\nvar_dump($states);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/state \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'retrieve', + endpoint: '/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}', + httpMethod: 'get', + summary: 'Get the state identified by the type and key.', + description: + 'Looks up the contents of a state event in a room. If the user is\njoined to the room then the state is taken from the current\nstate of the room. If the user has left the room then the state is\ntaken from the state of the room when they left.', + stainlessPath: '(resource) matrix.rooms.state > (method) retrieve', + qualified: 'client.matrix.rooms.state.retrieve', + params: ['roomId: string;', 'eventType: string;', 'stateKey: string;', "format?: 'content' | 'event';"], + response: 'object', + markdown: + "## retrieve\n\n`client.matrix.rooms.state.retrieve(roomId: string, eventType: string, stateKey: string, format?: 'content' | 'event'): object`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}`\n\nLooks up the contents of a state event in a room. If the user is\njoined to the room then the state is taken from the current\nstate of the room. If the user has left the room then the state is\ntaken from the state of the room when they left.\n\n### Parameters\n\n- `roomId: string`\n\n- `eventType: string`\n\n- `stateKey: string`\n\n- `format?: 'content' | 'event'`\n The format to use for the returned data. `content` (the default) will\nreturn only the content of the state event. `event` will return the entire\nevent in the usual format suitable for clients, including fields like event\nID, sender and timestamp.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst state = await client.matrix.rooms.state.retrieve('state_key', { roomId: '!636q39766251:example.com', eventType: 'm.room.name' });\n\nconsole.log(state);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.rooms.state.retrieve', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst state = await client.matrix.rooms.state.retrieve('state_key', {\n roomId: '!636q39766251:example.com',\n eventType: 'm.room.name',\n});\n\nconsole.log(state);", + }, + python: { + method: 'matrix.rooms.state.retrieve', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nstate = client.matrix.rooms.state.retrieve(\n state_key="state_key",\n room_id="!636q39766251:example.com",\n event_type="m.room.name",\n)\nprint(state)', + }, + go: { + method: 'client.Matrix.Rooms.State.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tstate, err := client.Matrix.Rooms.State.Get(\n\t\tcontext.TODO(),\n\t\t"state_key",\n\t\tbeeperdesktopapi.MatrixRoomStateGetParams{\n\t\t\tRoomID: "!636q39766251:example.com",\n\t\t\tEventType: "m.room.name",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", state)\n}\n', + }, + cli: { + method: 'state retrieve', + example: + "beeper-desktop-cli matrix:rooms:state retrieve \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:example.com' \\\n --event-type m.room.name \\\n --state-key state_key", + }, + php: { + method: 'matrix->rooms->state->retrieve', + example: + "matrix->rooms->state->retrieve(\n 'state_key',\n roomID: '!636q39766251:example.com',\n eventType: 'm.room.name',\n format: 'content',\n);\n\nvar_dump($state);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/state/$EVENT_TYPE/$STATE_KEY \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'retrieve', + endpoint: '/_matrix/client/v3/rooms/{roomId}/event/{eventId}', + httpMethod: 'get', + summary: 'Get a single event by event ID.', + description: + 'Get a single event based on `roomId/eventId`. You must have permission to\nretrieve this event e.g. by being a member in the room for this event.', + stainlessPath: '(resource) matrix.rooms.events > (method) retrieve', + qualified: 'client.matrix.rooms.events.retrieve', + params: ['roomId: string;', 'eventId: string;'], + response: + '{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }', + markdown: + "## retrieve\n\n`client.matrix.rooms.events.retrieve(roomId: string, eventId: string): { content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: object; }`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/event/{eventId}`\n\nGet a single event based on `roomId/eventId`. You must have permission to\nretrieve this event e.g. by being a member in the room for this event.\n\n### Parameters\n\n- `roomId: string`\n\n- `eventId: string`\n\n### Returns\n\n- `{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }`\n The format used for events when they are returned from a homeserver to a client\nvia the Client-Server API, or sent to an Application Service via the Application Services API.\n\n - `content: object`\n - `event_id: string`\n - `origin_server_ts: number`\n - `room_id: string`\n - `sender: string`\n - `type: string`\n - `state_key?: string`\n - `unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst event = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', { roomId: '!636q39766251:matrix.org' });\n\nconsole.log(event);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.rooms.events.retrieve', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst event = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', {\n roomId: '!636q39766251:matrix.org',\n});\n\nconsole.log(event.event_id);", + }, + python: { + method: 'matrix.rooms.events.retrieve', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nevent = client.matrix.rooms.events.retrieve(\n event_id="$asfDuShaf7Gafaw:matrix.org",\n room_id="!636q39766251:matrix.org",\n)\nprint(event.event_id)', + }, + go: { + method: 'client.Matrix.Rooms.Events.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tevent, err := client.Matrix.Rooms.Events.Get(\n\t\tcontext.TODO(),\n\t\t"$asfDuShaf7Gafaw:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomEventGetParams{\n\t\t\tRoomID: "!636q39766251:matrix.org",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", event.EventID)\n}\n', + }, + cli: { + method: 'events retrieve', + example: + "beeper-desktop-cli matrix:rooms:events retrieve \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:matrix.org' \\\n --event-id '$asfDuShaf7Gafaw:matrix.org'", + }, + php: { + method: 'matrix->rooms->events->retrieve', + example: + "matrix->rooms->events->retrieve(\n '$asfDuShaf7Gafaw:matrix.org', roomID: '!636q39766251:matrix.org'\n);\n\nvar_dump($event);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/event/$EVENT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'whoami', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami', + httpMethod: 'get', + summary: 'Get info about the bridge and your logins.', + description: + 'Get all info that is useful for presenting this bridge in a manager interface.\n* Server details: remote network details, available login flows, homeserver name, bridge bot user ID, command prefix\n* User details: management room ID, list of logins with current state and info\n', + stainlessPath: '(resource) matrix.bridges.auth > (method) whoami', + qualified: 'client.matrix.bridges.auth.whoami', + params: ['bridgeID: string;'], + response: + "{ bridge_bot: string; command_prefix: string; homeserver: string; login_flows: { id: string; description: string; name: string; }[]; logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]; network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }; management_room?: string; }", + markdown: + "## whoami\n\n`client.matrix.bridges.auth.whoami(bridgeID: string): { bridge_bot: string; command_prefix: string; homeserver: string; login_flows: object[]; logins: object[]; network: object; management_room?: string; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami`\n\nGet all info that is useful for presenting this bridge in a manager interface.\n* Server details: remote network details, available login flows, homeserver name, bridge bot user ID, command prefix\n* User details: management room ID, list of logins with current state and info\n\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ bridge_bot: string; command_prefix: string; homeserver: string; login_flows: { id: string; description: string; name: string; }[]; logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]; network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }; management_room?: string; }`\n Info about the bridge and user\n\n - `bridge_bot: string`\n - `command_prefix: string`\n - `homeserver: string`\n - `login_flows: { id: string; description: string; name: string; }[]`\n - `logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]`\n - `network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }`\n - `management_room?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.whoami('bridgeID');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.auth.whoami', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.whoami('bridgeID');\n\nconsole.log(response.bridge_bot);", + }, + python: { + method: 'matrix.bridges.auth.whoami', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.whoami(\n "bridgeID",\n)\nprint(response.bridge_bot)', + }, + go: { + method: 'client.Matrix.Bridges.Auth.Whoami', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.Whoami(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.BridgeBot)\n}\n', + }, + cli: { + method: 'auth whoami', + example: + "beeper-desktop-cli matrix:bridges:auth whoami \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + }, + php: { + method: 'matrix->bridges->auth->whoami', + example: + "matrix->bridges->auth->whoami('bridgeID');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/whoami \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'list_flows', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows', + httpMethod: 'get', + summary: 'Get the available login flows.', + description: 'Get the available login flows.', + stainlessPath: '(resource) matrix.bridges.auth > (method) list_flows', + qualified: 'client.matrix.bridges.auth.listFlows', + params: ['bridgeID: string;'], + response: '{ flows?: { id: string; description: string; name: string; }[]; }', + markdown: + "## list_flows\n\n`client.matrix.bridges.auth.listFlows(bridgeID: string): { flows?: object[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows`\n\nGet the available login flows.\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ flows?: { id: string; description: string; name: string; }[]; }`\n\n - `flows?: { id: string; description: string; name: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.listFlows('bridgeID');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.auth.listFlows', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.listFlows('bridgeID');\n\nconsole.log(response.flows);", + }, + python: { + method: 'matrix.bridges.auth.list_flows', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.list_flows(\n "bridgeID",\n)\nprint(response.flows)', + }, + go: { + method: 'client.Matrix.Bridges.Auth.ListFlows', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.ListFlows(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Flows)\n}\n', + }, + cli: { + method: 'auth list_flows', + example: + "beeper-desktop-cli matrix:bridges:auth list-flows \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + }, + php: { + method: 'matrix->bridges->auth->listFlows', + example: + "matrix->bridges->auth->listFlows('bridgeID');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/flows \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'list_logins', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins', + httpMethod: 'get', + summary: 'Get the login IDs of the current user.', + description: 'Get the login IDs of the current user.', + stainlessPath: '(resource) matrix.bridges.auth > (method) list_logins', + qualified: 'client.matrix.bridges.auth.listLogins', + params: ['bridgeID: string;'], + response: '{ login_ids?: string[]; }', + markdown: + "## list_logins\n\n`client.matrix.bridges.auth.listLogins(bridgeID: string): { login_ids?: string[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins`\n\nGet the login IDs of the current user.\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ login_ids?: string[]; }`\n\n - `login_ids?: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.listLogins('bridgeID');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.auth.listLogins', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.listLogins('bridgeID');\n\nconsole.log(response.login_ids);", + }, + python: { + method: 'matrix.bridges.auth.list_logins', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.list_logins(\n "bridgeID",\n)\nprint(response.login_ids)', + }, + go: { + method: 'client.Matrix.Bridges.Auth.ListLogins', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.ListLogins(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.LoginIDs)\n}\n', + }, + cli: { + method: 'auth list_logins', + example: + "beeper-desktop-cli matrix:bridges:auth list-logins \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + }, + php: { + method: 'matrix->bridges->auth->listLogins', + example: + "matrix->bridges->auth->listLogins('bridgeID');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/logins \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'start_login', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}', + httpMethod: 'post', + summary: 'Start a new login process.', + description: + "This endpoint starts a new login process, which is used to log into the bridge.\n\nThe basic flow of the entire login, including calling this endpoint, is:\n1. Call `GET /v3/login/flows` to get the list of available flows.\n If there's more than one flow, ask the user to pick which one they want to use.\n2. Call this endpoint with the chosen flow ID to start the login.\n The first login step will be returned.\n3. Render the information provided in the step.\n4. Call the `/login/step/...` endpoint corresponding to the step type:\n * For `user_input` and `cookies`, acquire the requested fields before calling the endpoint.\n * For `display_and_wait`, call the endpoint immediately\n (as there's nothing to acquire on the client side).\n5. Handle the data returned by the login step endpoint:\n * If an error is returned, the login has failed and must be restarted\n (from either step 1 or step 2) if the user wants to try again.\n * If step type `complete` is returned, the login finished successfully.\n * Otherwise, go to step 3 with the new data.\n", + stainlessPath: '(resource) matrix.bridges.auth > (method) start_login', + qualified: 'client.matrix.bridges.auth.startLogin', + params: ['bridgeID: string;', 'flowID: string;', 'login_id?: string;'], + response: + "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + markdown: + "## start_login\n\n`client.matrix.bridges.auth.startLogin(bridgeID: string, flowID: string, login_id?: string): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}`\n\nThis endpoint starts a new login process, which is used to log into the bridge.\n\nThe basic flow of the entire login, including calling this endpoint, is:\n1. Call `GET /v3/login/flows` to get the list of available flows.\n If there's more than one flow, ask the user to pick which one they want to use.\n2. Call this endpoint with the chosen flow ID to start the login.\n The first login step will be returned.\n3. Render the information provided in the step.\n4. Call the `/login/step/...` endpoint corresponding to the step type:\n * For `user_input` and `cookies`, acquire the requested fields before calling the endpoint.\n * For `display_and_wait`, call the endpoint immediately\n (as there's nothing to acquire on the client side).\n5. Handle the data returned by the login step endpoint:\n * If an error is returned, the login has failed and must be restarted\n (from either step 1 or step 2) if the user wants to try again.\n * If step type `complete` is returned, the login finished successfully.\n * Otherwise, go to step 3 with the new data.\n\n\n### Parameters\n\n- `bridgeID: string`\n\n- `flowID: string`\n\n- `login_id?: string`\n An existing login ID to re-login as. If this is specified and the user logs into a different account, the provided ID will be logged out.\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.auth.startLogin', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' });\n\nconsole.log(response);", + }, + python: { + method: 'matrix.bridges.auth.start_login', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.start_login(\n flow_id="qr",\n bridge_id="bridgeID",\n)\nprint(response)', + }, + go: { + method: 'client.Matrix.Bridges.Auth.StartLogin', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.StartLogin(\n\t\tcontext.TODO(),\n\t\t"qr",\n\t\tbeeperdesktopapi.MatrixBridgeAuthStartLoginParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'auth start_login', + example: + "beeper-desktop-cli matrix:bridges:auth start-login \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --flow-id qr", + }, + php: { + method: 'matrix->bridges->auth->startLogin', + example: + "matrix->bridges->auth->startLogin(\n 'qr', bridgeID: 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/start/$FLOW_ID \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'submit_user_input', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input', + httpMethod: 'post', + summary: 'Submit user input in a login process.', + description: 'Submit user input in a login process.', + stainlessPath: '(resource) matrix.bridges.auth > (method) submit_user_input', + qualified: 'client.matrix.bridges.auth.submitUserInput', + params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;', 'body: object;'], + response: + "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + markdown: + "## submit_user_input\n\n`client.matrix.bridges.auth.submitUserInput(bridgeID: string, loginProcessID: string, stepID: string, body: object): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input`\n\nSubmit user input in a login process.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n- `body: object`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.submitUserInput('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.auth.submitUserInput', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.submitUserInput('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);", + }, + python: { + method: 'matrix.bridges.auth.submit_user_input', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.submit_user_input(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n body={\n "foo": "string"\n },\n)\nprint(response)', + }, + go: { + method: 'client.Matrix.Bridges.Auth.SubmitUserInput', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.SubmitUserInput(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthSubmitUserInputParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t\tBody: map[string]string{\n\t\t\t\t"foo": "string",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'auth submit_user_input', + example: + "beeper-desktop-cli matrix:bridges:auth submit-user-input \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID \\\n --body '{foo: string}'", + }, + php: { + method: 'matrix->bridges->auth->submitUserInput', + example: + "matrix->bridges->auth->submitUserInput(\n 'stepID',\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: ['foo' => 'string'],\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/user_input \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "foo": "string"\n }\'', + }, + }, + }, + { + name: 'submit_cookies', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies', + httpMethod: 'post', + summary: 'Submit extracted cookies in a login process.', + description: 'Submit extracted cookies in a login process.', + stainlessPath: '(resource) matrix.bridges.auth > (method) submit_cookies', + qualified: 'client.matrix.bridges.auth.submitCookies', + params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;', 'body: object;'], + response: + "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + markdown: + "## submit_cookies\n\n`client.matrix.bridges.auth.submitCookies(bridgeID: string, loginProcessID: string, stepID: string, body: object): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies`\n\nSubmit extracted cookies in a login process.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n- `body: object`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.submitCookies('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.auth.submitCookies', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.submitCookies('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);", + }, + python: { + method: 'matrix.bridges.auth.submit_cookies', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.submit_cookies(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n body={\n "foo": "string"\n },\n)\nprint(response)', + }, + go: { + method: 'client.Matrix.Bridges.Auth.SubmitCookies', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.SubmitCookies(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthSubmitCookiesParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t\tBody: map[string]string{\n\t\t\t\t"foo": "string",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'auth submit_cookies', + example: + "beeper-desktop-cli matrix:bridges:auth submit-cookies \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID \\\n --body '{foo: string}'", + }, php: { - method: 'focus', + method: 'matrix->bridges->auth->submitCookies', example: - "focus(\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n draftAttachmentPath: 'draftAttachmentPath',\n draftText: 'draftText',\n messageID: 'messageID',\n);\n\nvar_dump($response);", + "matrix->bridges->auth->submitCookies(\n 'stepID',\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: ['foo' => 'string'],\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/focus \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/cookies \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "foo": "string"\n }\'', }, }, }, { - name: 'search', - endpoint: '/v1/search', - httpMethod: 'get', - summary: 'Search', - description: - 'Returns matching chats, participant name matches in groups, and the first page of messages in one call. Paginate messages via search-messages. Paginate chats via search-chats.', - stainlessPath: '(resource) $client > (method) search', - qualified: 'client.search', - params: ['query: string;'], + name: 'wait_for_step', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait', + httpMethod: 'post', + summary: 'Wait for the next step after displaying data to the user.', + description: 'Wait for the next step after displaying data to the user.', + stainlessPath: '(resource) matrix.bridges.auth > (method) wait_for_step', + qualified: 'client.matrix.bridges.auth.waitForStep', + params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;'], response: - '{ results: { chats: object[]; in_groups: object[]; messages: { chats: object; hasMore: boolean; items: message[]; newestCursor: string; oldestCursor: string; }; }; }', + "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", markdown: - "## search\n\n`client.search(query: string): { results: object; }`\n\n**get** `/v1/search`\n\nReturns matching chats, participant name matches in groups, and the first page of messages in one call. Paginate messages via search-messages. Paginate chats via search-chats.\n\n### Parameters\n\n- `query: string`\n User-typed search text. Literal word matching (non-semantic).\n\n### Returns\n\n- `{ results: { chats: object[]; in_groups: object[]; messages: { chats: object; hasMore: boolean; items: message[]; newestCursor: string; oldestCursor: string; }; }; }`\n\n - `results: { chats: { id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }[]; in_groups: { id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }[]; messages: { chats: object; hasMore: boolean; items: { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }[]; newestCursor: string; oldestCursor: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.search({ query: 'x' });\n\nconsole.log(response);\n```", + "## wait_for_step\n\n`client.matrix.bridges.auth.waitForStep(bridgeID: string, loginProcessID: string, stepID: string): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait`\n\nWait for the next step after displaying data to the user.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.waitForStep('stepID', { bridgeID: 'bridgeID', loginProcessID: 'loginProcessID' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.search', + method: 'client.matrix.bridges.auth.waitForStep', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.search({ query: 'x' });\n\nconsole.log(response.results);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.waitForStep('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n});\n\nconsole.log(response);", }, python: { - method: 'search', + method: 'matrix.bridges.auth.wait_for_step', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.search(\n query="x",\n)\nprint(response.results)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.wait_for_step(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n)\nprint(response)', }, go: { - method: 'client.Search', + method: 'client.Matrix.Bridges.Auth.WaitForStep', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Search(context.TODO(), beeperdesktopapi.SearchParams{\n\t\tQuery: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Results)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.WaitForStep(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthWaitForStepParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'auth wait_for_step', + example: + "beeper-desktop-cli matrix:bridges:auth wait-for-step \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID", }, php: { - method: 'search', + method: 'matrix->bridges->auth->waitForStep', example: - "search(query: 'x');\n\nvar_dump($response);", + "matrix->bridges->auth->waitForStep(\n 'stepID', bridgeID: 'bridgeID', loginProcessID: 'loginProcessID'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/display_and_wait \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'logout', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}', + httpMethod: 'post', + summary: 'Log out of an existing login.', + description: 'Log out of an existing login.', + stainlessPath: '(resource) matrix.bridges.auth > (method) logout', + qualified: 'client.matrix.bridges.auth.logout', + params: ['bridgeID: string;', 'loginID: string;'], + response: 'object', + markdown: + "## logout\n\n`client.matrix.bridges.auth.logout(bridgeID: string, loginID: string): object`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}`\n\nLog out of an existing login.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginID: string`\n The unique ID of a login. Defined by the network connector.\n\n### Returns\n\n- `object`\n Empty object\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.auth.logout', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', {\n bridgeID: 'bridgeID',\n});\n\nconsole.log(response);", + }, + python: { + method: 'matrix.bridges.auth.logout', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.logout(\n login_id="bcc68892-b180-414f-9516-b4aadf7d0496",\n bridge_id="bridgeID",\n)\nprint(response)', + }, + go: { + method: 'client.Matrix.Bridges.Auth.Logout', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.Logout(\n\t\tcontext.TODO(),\n\t\t"bcc68892-b180-414f-9516-b4aadf7d0496",\n\t\tbeeperdesktopapi.MatrixBridgeAuthLogoutParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'auth logout', + example: + "beeper-desktop-cli matrix:bridges:auth logout \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-id bcc68892-b180-414f-9516-b4aadf7d0496", + }, + php: { + method: 'matrix->bridges->auth->logout', + example: + "matrix->bridges->auth->logout(\n 'bcc68892-b180-414f-9516-b4aadf7d0496', bridgeID: 'bridgeID'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/logout/$LOGIN_ID \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { name: 'list', - endpoint: '/v1/accounts', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts', httpMethod: 'get', - summary: 'List Chat Accounts', - description: - 'List Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.', - stainlessPath: '(resource) accounts > (method) list', - qualified: 'client.accounts.list', + summary: 'Get a list of contacts.', + description: 'Get a list of contacts.', + stainlessPath: '(resource) matrix.bridges.contacts > (method) list', + qualified: 'client.matrix.bridges.contacts.list', + params: ['bridgeID: string;', 'login_id?: string;'], response: - "{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]", + '{ contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }', markdown: - "## list\n\n`client.accounts.list(): object[]`\n\n**get** `/v1/accounts`\n\nList Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.\n\n### Returns\n\n- `{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]`\n Accounts configured on this device. Includes accountID, bridge metadata, optional network name, and user identity.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);\n```", + "## list\n\n`client.matrix.bridges.contacts.list(bridgeID: string, login_id?: string): { contacts?: object[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts`\n\nGet a list of contacts.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }`\n\n - `contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst contacts = await client.matrix.bridges.contacts.list('bridgeID');\n\nconsole.log(contacts);\n```", perLanguage: { typescript: { - method: 'client.accounts.list', + method: 'client.matrix.bridges.contacts.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst contacts = await client.matrix.bridges.contacts.list('bridgeID');\n\nconsole.log(contacts.contacts);", }, python: { - method: 'accounts.list', + method: 'matrix.bridges.contacts.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccounts = client.accounts.list()\nprint(accounts)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\ncontacts = client.matrix.bridges.contacts.list(\n bridge_id="bridgeID",\n)\nprint(contacts.contacts)', }, go: { - method: 'client.Accounts.List', + method: 'client.Matrix.Bridges.Contacts.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccounts, err := client.Accounts.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accounts)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tcontacts, err := client.Matrix.Bridges.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"bridgeID",\n\t\tbeeperdesktopapi.MatrixBridgeContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", contacts.Contacts)\n}\n', + }, + cli: { + method: 'contacts list', + example: + "beeper-desktop-cli matrix:bridges:contacts list \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", }, php: { - method: 'accounts->list', + method: 'matrix->bridges->contacts->list', example: - "accounts->list();\n\nvar_dump($accounts);", + "matrix->bridges->contacts->list(\n 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496'\n);\n\nvar_dump($contacts);", }, http: { example: - 'curl http://localhost:23373/v1/accounts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/contacts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { name: 'search', - endpoint: '/v1/accounts/{accountID}/contacts', - httpMethod: 'get', - summary: 'Search contacts', - description: - 'Search contacts on a specific account using merged account contacts, network search, and exact identifier lookup.', - stainlessPath: '(resource) accounts.contacts > (method) search', - qualified: 'client.accounts.contacts.search', - params: ['accountID: string;', 'query: string;'], + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users', + httpMethod: 'post', + summary: 'Search for users on the remote network', + description: 'Search for users on the remote network', + stainlessPath: '(resource) matrix.bridges.users > (method) search', + qualified: 'client.matrix.bridges.users.search', + params: ['bridgeID: string;', 'login_id?: string;', 'query?: string;'], response: - '{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }', + '{ results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }', markdown: - "## search\n\n`client.accounts.contacts.search(accountID: string, query: string): { items: user[]; }`\n\n**get** `/v1/accounts/{accountID}/contacts`\n\nSearch contacts on a specific account using merged account contacts, network search, and exact identifier lookup.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `query: string`\n Text to search users by. Network-specific behavior.\n\n### Returns\n\n- `{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }`\n\n - `items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response);\n```", + "## search\n\n`client.matrix.bridges.users.search(bridgeID: string, login_id?: string, query?: string): { results?: object[]; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users`\n\nSearch for users on the remote network\n\n### Parameters\n\n- `bridgeID: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n- `query?: string`\n The search query to send to the remote network\n\n### Returns\n\n- `{ results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }`\n\n - `results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.users.search('bridgeID');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.accounts.contacts.search', + method: 'client.matrix.bridges.users.search', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response.items);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.users.search('bridgeID');\n\nconsole.log(response.results);", }, python: { - method: 'accounts.contacts.search', + method: 'matrix.bridges.users.search', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.accounts.contacts.search(\n account_id="accountID",\n query="x",\n)\nprint(response.items)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.users.search(\n bridge_id="bridgeID",\n)\nprint(response.results)', }, go: { - method: 'client.Accounts.Contacts.Search', + method: 'client.Matrix.Bridges.Users.Search', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Accounts.Contacts.Search(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactSearchParams{\n\t\t\tQuery: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Items)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Users.Search(\n\t\tcontext.TODO(),\n\t\t"bridgeID",\n\t\tbeeperdesktopapi.MatrixBridgeUserSearchParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Results)\n}\n', + }, + cli: { + method: 'users search', + example: + "beeper-desktop-cli matrix:bridges:users search \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", }, php: { - method: 'accounts->contacts->search', + method: 'matrix->bridges->users->search', example: - "accounts->contacts->search('accountID', query: 'x');\n\nvar_dump($response);", + "matrix->bridges->users->search(\n 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496', query: 'query'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID/contacts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/search_users \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'list', - endpoint: '/v1/accounts/{accountID}/contacts/list', + name: 'resolve', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}', httpMethod: 'get', - summary: 'List contacts', - description: 'List merged contacts for a specific account with cursor-based pagination.', - stainlessPath: '(resource) accounts.contacts > (method) list', - qualified: 'client.accounts.contacts.list', + summary: 'Resolve an identifier to a user on the remote network.', + description: 'Resolve an identifier to a user on the remote network.', + stainlessPath: '(resource) matrix.bridges.users > (method) resolve', + qualified: 'client.matrix.bridges.users.resolve', + params: ['bridgeID: string;', 'identifier: string;', 'login_id?: string;'], + response: + '{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }', + markdown: + "## resolve\n\n`client.matrix.bridges.users.resolve(bridgeID: string, identifier: string, login_id?: string): { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}`\n\nResolve an identifier to a user on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `identifier: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n A successfully resolved identifier.\n\n - `id: string`\n - `avatar_url?: string`\n - `dm_room_mxid?: string`\n - `identifiers?: string[]`\n - `mxid?: string`\n - `name?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.users.resolve', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response.id);", + }, + python: { + method: 'matrix.bridges.users.resolve', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.users.resolve(\n identifier="identifier",\n bridge_id="bridgeID",\n)\nprint(response.id)', + }, + go: { + method: 'client.Matrix.Bridges.Users.Resolve', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Users.Resolve(\n\t\tcontext.TODO(),\n\t\t"identifier",\n\t\tbeeperdesktopapi.MatrixBridgeUserResolveParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + }, + cli: { + method: 'users resolve', + example: + "beeper-desktop-cli matrix:bridges:users resolve \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --identifier identifier", + }, + php: { + method: 'matrix->bridges->users->resolve', + example: + "matrix->bridges->users->resolve(\n 'identifier',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/resolve_identifier/$IDENTIFIER \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'create_dm', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}', + httpMethod: 'post', + summary: 'Create a direct chat with a user on the remote network.', + description: 'Create a direct chat with a user on the remote network.', + stainlessPath: '(resource) matrix.bridges.rooms > (method) create_dm', + qualified: 'client.matrix.bridges.rooms.createDm', + params: ['bridgeID: string;', 'identifier: string;', 'login_id?: string;'], + response: + '{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }', + markdown: + "## create_dm\n\n`client.matrix.bridges.rooms.createDm(bridgeID: string, identifier: string, login_id?: string): { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}`\n\nCreate a direct chat with a user on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `identifier: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n A successfully resolved identifier.\n\n - `id: string`\n - `avatar_url?: string`\n - `dm_room_mxid?: string`\n - `identifiers?: string[]`\n - `mxid?: string`\n - `name?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.rooms.createDm', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response.id);", + }, + python: { + method: 'matrix.bridges.rooms.create_dm', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.rooms.create_dm(\n identifier="identifier",\n bridge_id="bridgeID",\n)\nprint(response.id)', + }, + go: { + method: 'client.Matrix.Bridges.Rooms.NewDm', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Rooms.NewDm(\n\t\tcontext.TODO(),\n\t\t"identifier",\n\t\tbeeperdesktopapi.MatrixBridgeRoomNewDmParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + }, + cli: { + method: 'rooms create_dm', + example: + "beeper-desktop-cli matrix:bridges:rooms create-dm \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --identifier identifier", + }, + php: { + method: 'matrix->bridges->rooms->createDm', + example: + "matrix->bridges->rooms->createDm(\n 'identifier',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/create_dm/$IDENTIFIER \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'create_group', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}', + httpMethod: 'post', + summary: 'Create a group chat on the remote network.', + description: 'Create a group chat on the remote network.', + stainlessPath: '(resource) matrix.bridges.rooms > (method) create_group', + qualified: 'client.matrix.bridges.rooms.createGroup', params: [ - 'accountID: string;', - 'cursor?: string;', - "direction?: 'after' | 'before';", - 'limit?: number;', - 'query?: string;', + 'bridgeID: string;', + 'groupType: string;', + 'login_id?: string;', + 'avatar?: { url?: string; };', + 'disappear?: { timer?: number; type?: string; };', + 'name?: { name?: string; };', + 'parent?: object;', + 'participants?: string[];', + 'room_id?: string;', + 'topic?: { topic?: string; };', + 'type?: string;', + 'username?: string;', ], - response: - '{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }', + response: '{ id: string; mxid: string; }', markdown: - "## list\n\n`client.accounts.contacts.list(accountID: string, cursor?: string, direction?: 'after' | 'before', limit?: number, query?: string): { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n\n**get** `/v1/accounts/{accountID}/contacts/list`\n\nList merged contacts for a specific account with cursor-based pagination.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `limit?: number`\n Maximum contacts to return per page.\n\n- `query?: string`\n Optional search query for blended contact lookup.\n\n### Returns\n\n- `{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n User the account belongs to.\n\n - `id: string`\n - `cannotMessage?: boolean`\n - `email?: string`\n - `fullName?: string`\n - `imgURL?: string`\n - `isSelf?: boolean`\n - `phoneNumber?: string`\n - `username?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user);\n}\n```", + "## create_group\n\n`client.matrix.bridges.rooms.createGroup(bridgeID: string, groupType: string, login_id?: string, avatar?: { url?: string; }, disappear?: { timer?: number; type?: string; }, name?: { name?: string; }, parent?: object, participants?: string[], room_id?: string, topic?: { topic?: string; }, type?: string, username?: string): { id: string; mxid: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}`\n\nCreate a group chat on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `groupType: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n- `avatar?: { url?: string; }`\n The `m.room.avatar` event content for the room.\n - `url?: string`\n\n- `disappear?: { timer?: number; type?: string; }`\n The `com.beeper.disappearing_timer` event content for the room.\n - `timer?: number`\n - `type?: string`\n\n- `name?: { name?: string; }`\n The `m.room.name` event content for the room.\n - `name?: string`\n\n- `parent?: object`\n\n- `participants?: string[]`\n The users to add to the group initially.\n\n- `room_id?: string`\n An existing Matrix room ID to bridge to.\nThe other parameters must be already in sync with the room state when using this parameter.\n\n\n- `topic?: { topic?: string; }`\n The `m.room.topic` event content for the room.\n - `topic?: string`\n\n- `type?: string`\n The type of group to create.\n\n- `username?: string`\n The public username for the created group.\n\n### Returns\n\n- `{ id: string; mxid: string; }`\n A successfully created group chat.\n\n - `id: string`\n - `mxid: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.rooms.createGroup('groupType', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.accounts.contacts.list', + method: 'client.matrix.bridges.rooms.createGroup', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user.id);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.rooms.createGroup('groupType', {\n bridgeID: 'bridgeID',\n});\n\nconsole.log(response.id);", }, python: { - method: 'accounts.contacts.list', + method: 'matrix.bridges.rooms.create_group', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.accounts.contacts.list(\n account_id="accountID",\n)\npage = page.items[0]\nprint(page.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.rooms.create_group(\n group_type="groupType",\n bridge_id="bridgeID",\n)\nprint(response.id)', }, go: { - method: 'client.Accounts.Contacts.List', + method: 'client.Matrix.Bridges.Rooms.NewGroup', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Accounts.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Rooms.NewGroup(\n\t\tcontext.TODO(),\n\t\t"groupType",\n\t\tbeeperdesktopapi.MatrixBridgeRoomNewGroupParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + }, + cli: { + method: 'rooms create_group', + example: + "beeper-desktop-cli matrix:bridges:rooms create-group \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --group-type groupType", }, php: { - method: 'accounts->contacts->list', + method: 'matrix->bridges->rooms->createGroup', example: - "accounts->contacts->list(\n 'accountID',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n limit: 1,\n query: 'x',\n);\n\nvar_dump($page);", + "matrix->bridges->rooms->createGroup(\n 'groupType',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n avatar: ['url' => 'url'],\n disappear: ['timer' => 0, 'type' => 'type'],\n name: ['name' => 'name'],\n parent: (object) [],\n participants: ['string'],\n roomID: 'room_id',\n topic: ['topic' => 'topic'],\n type: 'channel',\n username: 'username',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID/contacts/list \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/create_group/$GROUP_TYPE \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'retrieve', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities', + httpMethod: 'get', + summary: 'Get bridge capabilities', + description: 'Get bridge capabilities', + stainlessPath: '(resource) matrix.bridges.capabilities > (method) retrieve', + qualified: 'client.matrix.bridges.capabilities.retrieve', + params: ['bridgeID: string;'], + response: 'object', + markdown: + "## retrieve\n\n`client.matrix.bridges.capabilities.retrieve(bridgeID: string): object`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities`\n\nGet bridge capabilities\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst capability = await client.matrix.bridges.capabilities.retrieve('bridgeID');\n\nconsole.log(capability);\n```", + perLanguage: { + typescript: { + method: 'client.matrix.bridges.capabilities.retrieve', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst capability = await client.matrix.bridges.capabilities.retrieve('bridgeID');\n\nconsole.log(capability);", + }, + python: { + method: 'matrix.bridges.capabilities.retrieve', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\ncapability = client.matrix.bridges.capabilities.retrieve(\n "bridgeID",\n)\nprint(capability)', + }, + go: { + method: 'client.Matrix.Bridges.Capabilities.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tcapability, err := client.Matrix.Bridges.Capabilities.Get(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", capability)\n}\n', + }, + cli: { + method: 'capabilities retrieve', + example: + "beeper-desktop-cli matrix:bridges:capabilities retrieve \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + }, + php: { + method: 'matrix->bridges->capabilities->retrieve', + example: + "matrix->bridges->capabilities->retrieve('bridgeID');\n\nvar_dump($capability);", + }, + http: { + example: + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/capabilities \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, @@ -292,6 +2231,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Get(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatGetParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, + cli: { + method: 'chats retrieve', + example: + "beeper-desktop-cli chats retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'chats->retrieve', example: @@ -338,6 +2282,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.New(context.TODO(), beeperdesktopapi.ChatNewParams{\n\t\tAccountID: "accountID",\n\t\tParticipantIDs: []string{"string"},\n\t\tType: beeperdesktopapi.ChatNewParamsTypeSingle,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat)\n}\n', }, + cli: { + method: 'chats create', + example: + "beeper-desktop-cli chats create \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --participant-id string \\\n --type single", + }, php: { method: 'chats->create', example: @@ -384,6 +2333,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Start(context.TODO(), beeperdesktopapi.ChatStartParams{\n\t\tAccountID: "accountID",\n\t\tUser: beeperdesktopapi.ChatStartParamsUser{},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, + cli: { + method: 'chats start', + example: + "beeper-desktop-cli chats start \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --user '{}'", + }, php: { method: 'chats->start', example: @@ -425,6 +2379,10 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.List(context.TODO(), beeperdesktopapi.ChatListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, + cli: { + method: 'chats list', + example: "beeper-desktop-cli chats list \\\n --access-token 'My Access Token'", + }, php: { method: 'chats->list', example: @@ -478,6 +2436,10 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.Search(context.TODO(), beeperdesktopapi.ChatSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, + cli: { + method: 'chats search', + example: "beeper-desktop-cli chats search \\\n --access-token 'My Access Token'", + }, php: { method: 'chats->search', example: @@ -517,6 +2479,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Archive(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatArchiveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, + cli: { + method: 'chats archive', + example: + "beeper-desktop-cli chats archive \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'chats->archive', example: @@ -569,6 +2536,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Update(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, + cli: { + method: 'chats update', + example: + "beeper-desktop-cli chats update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'chats->update', example: @@ -609,6 +2581,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkRead(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkReadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, + cli: { + method: 'chats mark_read', + example: + "beeper-desktop-cli chats mark-read \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'chats->markRead', example: @@ -649,6 +2626,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkUnread(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkUnreadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, + cli: { + method: 'chats mark_unread', + example: + "beeper-desktop-cli chats mark-unread \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'chats->markUnread', example: @@ -690,6 +2672,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.NotifyAnyway(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatNotifyAnywayParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, + cli: { + method: 'chats notify_anyway', + example: + "beeper-desktop-cli chats notify-anyway \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'chats->notifyAnyway', example: @@ -728,6 +2715,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"time"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.New(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatReminderNewParams{\n\t\t\tReminder: beeperdesktopapi.ChatReminderNewParamsReminder{\n\t\t\t\tRemindAt: time.Now(),\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, + cli: { + method: 'reminders create', + example: + "beeper-desktop-cli chats:reminders create \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --reminder \"{remindAt: '2025-08-31T23:30:12.520Z'}\"", + }, php: { method: 'chats->reminders->create', example: @@ -766,6 +2758,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.Delete(context.TODO(), "!NCdzlIaMjZUmvmvyHU:beeper.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, + cli: { + method: 'reminders delete', + example: + "beeper-desktop-cli chats:reminders delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'chats->reminders->delete', example: @@ -806,6 +2803,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Messages.Reactions.Add(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.ChatMessageReactionAddParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tReactionKey: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ChatID)\n}\n', }, + cli: { + method: 'reactions add', + example: + "beeper-desktop-cli chats:messages:reactions add \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", + }, php: { method: 'chats->messages->reactions->add', example: @@ -845,6 +2847,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treaction, err := client.Chats.Messages.Reactions.Delete(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.ChatMessageReactionDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tMessageID: "1343993",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reaction.ChatID)\n}\n', }, + cli: { + method: 'reactions delete', + example: + "beeper-desktop-cli chats:messages:reactions delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", + }, php: { method: 'chats->messages->reactions->delete', example: @@ -899,6 +2906,10 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.Search(context.TODO(), beeperdesktopapi.MessageSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, + cli: { + method: 'messages search', + example: "beeper-desktop-cli messages search \\\n --access-token 'My Access Token'", + }, php: { method: 'messages->search', example: @@ -939,6 +2950,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.List(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, + cli: { + method: 'messages list', + example: + "beeper-desktop-cli messages list \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'messages->list', example: @@ -984,6 +3000,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Messages.Send(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageSendParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.PendingMessageID)\n}\n', }, + cli: { + method: 'messages send', + example: + "beeper-desktop-cli messages send \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + }, php: { method: 'messages->send', example: @@ -1025,6 +3046,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Get(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageGetParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message.ID)\n}\n', }, + cli: { + method: 'messages retrieve', + example: + "beeper-desktop-cli messages retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", + }, php: { method: 'messages->retrieve', example: @@ -1065,6 +3091,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Update(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageUpdateParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tText: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message)\n}\n', }, + cli: { + method: 'messages update', + example: + "beeper-desktop-cli messages update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --text x", + }, php: { method: 'messages->update', example: @@ -1104,6 +3135,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Messages.Delete(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, + cli: { + method: 'messages delete', + example: + "beeper-desktop-cli messages delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", + }, php: { method: 'messages->delete', example: @@ -1144,6 +3180,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Download(context.TODO(), beeperdesktopapi.AssetDownloadParams{\n\t\tURL: "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Error)\n}\n', }, + cli: { + method: 'assets download', + example: + "beeper-desktop-cli assets download \\\n --access-token 'My Access Token' \\\n --url mxc://example.org/Q4x9CqGz1pB3Oa6XgJ", + }, php: { method: 'assets->download', example: @@ -1185,6 +3226,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"bytes"\n\t"context"\n\t"fmt"\n\t"io"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Upload(context.TODO(), beeperdesktopapi.AssetUploadParams{\n\t\tFile: io.Reader(bytes.NewBuffer([]byte("Example data"))),\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', }, + cli: { + method: 'assets upload', + example: + "beeper-desktop-cli assets upload \\\n --access-token 'My Access Token' \\\n --file 'Example data'", + }, php: { method: 'assets->upload', example: @@ -1226,6 +3272,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.UploadBase64(context.TODO(), beeperdesktopapi.AssetUploadBase64Params{\n\t\tContent: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', }, + cli: { + method: 'assets upload_base64', + example: + "beeper-desktop-cli assets upload-base64 \\\n --access-token 'My Access Token' \\\n --content x", + }, php: { method: 'assets->uploadBase64', example: @@ -1266,6 +3317,10 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Serve(context.TODO(), beeperdesktopapi.AssetServeParams{\n\t\tURL: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, + cli: { + method: 'assets serve', + example: "beeper-desktop-cli assets serve \\\n --access-token 'My Access Token' \\\n --url x", + }, php: { method: 'assets->serve', example: @@ -1306,6 +3361,10 @@ const EMBEDDED_METHODS: MethodEntry[] = [ example: 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tinfo, err := client.Info.Get(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", info.App)\n}\n', }, + cli: { + method: 'info retrieve', + example: "beeper-desktop-cli info retrieve \\\n --access-token 'My Access Token'", + }, php: { method: 'info->retrieve', example: @@ -1320,6 +3379,11 @@ const EMBEDDED_METHODS: MethodEntry[] = [ ]; const EMBEDDED_READMES: { language: string; content: string }[] = [ + { + language: 'cli', + content: + "# Beeper Desktop CLI\n\nThe official CLI for the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/).\n\n\n\n## Installation\n\n### Installing with Homebrew\n\n~~~sh\nbrew install beeper/tap/beeper-desktop-cli\n~~~\n\n### Installing with Go\n\nTo test or install the CLI locally, you need [Go](https://go.dev/doc/install) version 1.22 or later installed.\n\n~~~sh\ngo install 'github.com/beeper/desktop-api-cli/cmd/beeper-desktop-cli@latest'\n~~~\n\nOnce you have run `go install`, the binary is placed in your Go bin directory:\n\n- **Default location**: `$HOME/go/bin` (or `$GOPATH/bin` if GOPATH is set)\n- **Check your path**: Run `go env GOPATH` to see the base directory\n\nIf commands aren't found after installation, add the Go bin directory to your PATH:\n\n~~~sh\n# Add to your shell profile (.zshrc, .bashrc, etc.)\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n~~~\n\n\n\n### Running Locally\n\nAfter cloning the git repository for this project, you can use the\n`scripts/run` script to run the tool locally:\n\n~~~sh\n./scripts/run args...\n~~~\n\n## Usage\n\nThe CLI follows a resource-based command structure:\n\n~~~sh\nbeeper-desktop-cli [resource] [flags...]\n~~~\n\n~~~sh\nbeeper-desktop-cli chats search \\\n --access-token 'My Access Token' \\\n --account-id matrix \\\n --account-id discordgo \\\n --account-id local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --include-muted \\\n --limit 3 \\\n --type single\n~~~\n\nFor details about specific commands, use the `--help` flag.\n\n### Environment variables\n\n| Environment variable | Description | Required |\n| --------------------- | ----------------------------------------------------------------------------------------------------- | -------- |\n| `BEEPER_ACCESS_TOKEN` | Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations. | yes |\n\n### Global flags\n\n- `--access-token` - Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations. (can also be set with `BEEPER_ACCESS_TOKEN` env var)\n- `--help` - Show command line usage\n- `--debug` - Enable debug logging (includes HTTP request/response details)\n- `--version`, `-v` - Show the CLI version\n- `--base-url` - Use a custom API backend URL\n- `--format` - Change the output format (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--format-error` - Change the output format for errors (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--transform` - Transform the data output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n- `--transform-error` - Transform the error output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n\n### Passing files as arguments\n\nTo pass files to your API, you can use the `@myfile.ext` syntax:\n\n~~~bash\nbeeper-desktop-cli --arg @abe.jpg\n~~~\n\nFiles can also be passed inside JSON or YAML blobs:\n\n~~~bash\nbeeper-desktop-cli --arg '{image: \"@abe.jpg\"}'\n# Equivalent:\nbeeper-desktop-cli < --username '\\@abe'\n~~~\n\n#### Explicit encoding\n\nFor JSON endpoints, the CLI tool does filetype sniffing to determine whether the\nfile contents should be sent as a string literal (for plain text files) or as a\nbase64-encoded string literal (for binary files). If you need to explicitly send\nthe file as either plain text or base64-encoded data, you can use\n`@file://myfile.txt` (for string encoding) or `@data://myfile.dat` (for\nbase64-encoding). Note that absolute paths will begin with `@file://` or\n`@data://`, followed by a third `/` (for example, `@file:///tmp/file.txt`).\n\n~~~bash\nbeeper-desktop-cli --arg @data://file.txt\n~~~\n\n## Linking different Go SDK versions\n\nYou can link the CLI against a different version of the Beeper Desktop Go SDK\nfor development purposes using the `./scripts/link` script.\n\nTo link to a specific version from a repository (version can be a branch,\ngit tag, or commit hash):\n\n~~~bash\n./scripts/link github.com/org/repo@version\n~~~\n\nTo link to a local copy of the SDK:\n\n~~~bash\n./scripts/link ../path/to/beeperdesktopapi-go\n~~~\n\nIf you run the link script without any arguments, it will default to `../beeperdesktopapi-go`.\n", + }, { language: 'go', content: @@ -1333,7 +3397,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'python', content: - '# Beeper Desktop Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beeper_desktop_api.svg?label=pypi%20(stable))](https://pypi.org/project/beeper_desktop_api/)\n\nThe Beeper Desktop Python library provides convenient access to the Beeper Desktop REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\n\n\n## MCP Server\n\nUse the Beeper Desktop MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40beeper%2Fdesktop-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBiZWVwZXIvZGVza3RvcC1tY3AiXSwiZW52Ijp7IkJFRVBFUl9BQ0NFU1NfVE9LRU4iOiJNeSBBY2Nlc3MgVG9rZW4ifX0)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40beeper%2Fdesktop-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40beeper%2Fdesktop-mcp%22%5D%2C%22env%22%3A%7B%22BEEPER_ACCESS_TOKEN%22%3A%22My%20Access%20Token%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nThe REST API documentation can be found on [developers.beeper.com](https://developers.beeper.com/desktop-api/). The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from the production repo\npip install git+ssh://git@github.com/beeper/desktop-api-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beeper_desktop_api`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\n\npage = client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n)\nprint(page.items)\n```\n\nWhile you can provide a `access_token` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEEPER_ACCESS_TOKEN="My Access Token"` to your `.env` file\nso that your Access Token is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeeperDesktop` instead of `BeeperDesktop` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nclient = AsyncBeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\n\nasync def main() -> None:\n page = await client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n )\n print(page.items)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from the production repo\npip install \'beeper_desktop_api[aiohttp] @ git+ssh://git@github.com/beeper/desktop-api-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beeper_desktop_api import DefaultAioHttpClient\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nasync def main() -> None:\n async with AsyncBeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n page = await client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n )\n print(page.items)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n## Pagination\n\nList methods in the Beeper Desktop API are paginated.\n\nThis library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nall_messages = []\n# Automatically fetches more pages as needed.\nfor message in client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n):\n # Do something with message here\n all_messages.append(message)\nprint(all_messages)\n```\n\nOr, asynchronously:\n\n```python\nimport asyncio\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nclient = AsyncBeeperDesktop()\n\nasync def main() -> None:\n all_messages = []\n # Iterate through items across all pages, issuing requests as needed.\n async for message in client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n):\n all_messages.append(message)\n print(all_messages)\n\nasyncio.run(main())\n```\n\nAlternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:\n\n```python\nfirst_page = await client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n)\nif first_page.has_next_page():\n print(f"will fetch next page using these details: {first_page.next_page_info()}")\n next_page = await first_page.get_next_page()\n print(f"number of items we just fetched: {len(next_page.items)}")\n\n# Remove `await` for non-async usage.\n```\n\nOr just work directly with the returned data:\n\n```python\nfirst_page = await client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n)\n\nprint(f"next page cursor: {first_page.oldest_cursor}") # => "next page cursor: ..."\nfor message in first_page.items:\n print(message.id)\n\n# Remove `await` for non-async usage.\n```\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nchat = client.chats.update(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n draft={\n "text": "text"\n },\n)\nprint(chat.draft)\n```\n\n## File uploads\n\nRequest parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.\n\n```python\nfrom pathlib import Path\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nclient.assets.upload(\n file=Path("/path/to/file"),\n)\n```\n\nThe async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically.\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beeper_desktop_api.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beeper_desktop_api.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beeper_desktop_api.APIError`.\n\n```python\nimport beeper_desktop_api\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\ntry:\n client.accounts.list()\nexcept beeper_desktop_api.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beeper_desktop_api.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beeper_desktop_api.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\n# Configure the default for all requests:\nclient = BeeperDesktop(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).accounts.list()\n```\n\n### Timeouts\n\nBy default requests time out after 30 seconds. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\n# Configure the default for all requests:\nclient = BeeperDesktop(\n # 20 seconds (default is 30 seconds)\n timeout=20.0,\n)\n\n# More granular control:\nclient = BeeperDesktop(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).accounts.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEEPER_LOG` to `info`.\n\n```shell\n$ export BEEPER_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.accounts.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\naccount = response.parse() # get the object that `accounts.list()` would have returned\nprint(account)\n```\n\nThese methods return an [`APIResponse`](https://github.com/beeper/desktop-api-python/tree/main/src/beeper_desktop_api/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/beeper/desktop-api-python/tree/main/src/beeper_desktop_api/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.accounts.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beeper_desktop_api import BeeperDesktop, DefaultHttpxClient\n\nclient = BeeperDesktop(\n # Or use the `BEEPER_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beeper_desktop_api import BeeperDesktop\n\nwith BeeperDesktop() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/beeper/desktop-api-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beeper_desktop_api\nprint(beeper_desktop_api.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', + '# Beeper Desktop Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beeper_desktop_api.svg?label=pypi%20(stable))](https://pypi.org/project/beeper_desktop_api/)\n\nThe Beeper Desktop Python library provides convenient access to the Beeper Desktop REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\n\n\n## MCP Server\n\nUse the Beeper Desktop MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40beeper%2Fdesktop-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBiZWVwZXIvZGVza3RvcC1tY3AiXSwiZW52Ijp7IkJFRVBFUl9BQ0NFU1NfVE9LRU4iOiJNeSBBY2Nlc3MgVG9rZW4ifX0)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40beeper%2Fdesktop-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40beeper%2Fdesktop-mcp%22%5D%2C%22env%22%3A%7B%22BEEPER_ACCESS_TOKEN%22%3A%22My%20Access%20Token%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nThe REST API documentation can be found on [developers.beeper.com](https://developers.beeper.com/desktop-api/). The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from the production repo\npip install git+ssh://git@github.com/beeper/desktop-api-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beeper_desktop_api`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\n\npage = client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n)\nprint(page.items)\n```\n\nWhile you can provide a `access_token` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEEPER_ACCESS_TOKEN="My Access Token"` to your `.env` file\nso that your Access Token is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeeperDesktop` instead of `BeeperDesktop` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nclient = AsyncBeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\n\nasync def main() -> None:\n page = await client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n )\n print(page.items)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from the production repo\npip install \'beeper_desktop_api[aiohttp] @ git+ssh://git@github.com/beeper/desktop-api-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beeper_desktop_api import DefaultAioHttpClient\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nasync def main() -> None:\n async with AsyncBeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n page = await client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n )\n print(page.items)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n## Pagination\n\nList methods in the Beeper Desktop API are paginated.\n\nThis library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nall_messages = []\n# Automatically fetches more pages as needed.\nfor message in client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n):\n # Do something with message here\n all_messages.append(message)\nprint(all_messages)\n```\n\nOr, asynchronously:\n\n```python\nimport asyncio\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nclient = AsyncBeeperDesktop()\n\nasync def main() -> None:\n all_messages = []\n # Iterate through items across all pages, issuing requests as needed.\n async for message in client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n):\n all_messages.append(message)\n print(all_messages)\n\nasyncio.run(main())\n```\n\nAlternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:\n\n```python\nfirst_page = await client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n)\nif first_page.has_next_page():\n print(f"will fetch next page using these details: {first_page.next_page_info()}")\n next_page = await first_page.get_next_page()\n print(f"number of items we just fetched: {len(next_page.items)}")\n\n# Remove `await` for non-async usage.\n```\n\nOr just work directly with the returned data:\n\n```python\nfirst_page = await client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n)\n\nprint(f"next page cursor: {first_page.oldest_cursor}") # => "next page cursor: ..."\nfor message in first_page.items:\n print(message.id)\n\n# Remove `await` for non-async usage.\n```\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nresponse = client.matrix.rooms.join(\n room_id_or_alias="!monkeys:matrix.org",\n third_party_signed={\n "token": "random8nonce",\n "mxid": "bob",\n "sender": "alice",\n "signatures": {\n "example.org": {\n "ed25519:0": "some9signature"\n }\n },\n },\n)\nprint(response.third_party_signed)\n```\n\n## File uploads\n\nRequest parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.\n\n```python\nfrom pathlib import Path\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nclient.assets.upload(\n file=Path("/path/to/file"),\n)\n```\n\nThe async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically.\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beeper_desktop_api.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beeper_desktop_api.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beeper_desktop_api.APIError`.\n\n```python\nimport beeper_desktop_api\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\ntry:\n client.accounts.list()\nexcept beeper_desktop_api.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beeper_desktop_api.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beeper_desktop_api.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\n# Configure the default for all requests:\nclient = BeeperDesktop(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).accounts.list()\n```\n\n### Timeouts\n\nBy default requests time out after 30 seconds. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\n# Configure the default for all requests:\nclient = BeeperDesktop(\n # 20 seconds (default is 30 seconds)\n timeout=20.0,\n)\n\n# More granular control:\nclient = BeeperDesktop(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).accounts.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEEPER_LOG` to `info`.\n\n```shell\n$ export BEEPER_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.accounts.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\naccount = response.parse() # get the object that `accounts.list()` would have returned\nprint(account)\n```\n\nThese methods return an [`APIResponse`](https://github.com/beeper/desktop-api-python/tree/main/src/beeper_desktop_api/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/beeper/desktop-api-python/tree/main/src/beeper_desktop_api/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.accounts.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beeper_desktop_api import BeeperDesktop, DefaultHttpxClient\n\nclient = BeeperDesktop(\n # Or use the `BEEPER_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beeper_desktop_api import BeeperDesktop\n\nwith BeeperDesktop() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/beeper/desktop-api-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beeper_desktop_api\nprint(beeper_desktop_api.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', }, { language: 'typescript', diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts index 509a8540..3cf2a1f2 100644 --- a/packages/mcp-server/src/methods.ts +++ b/packages/mcp-server/src/methods.ts @@ -22,6 +22,102 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/v1/search', }, + { + clientCallName: 'client.app.status', + fullyQualifiedName: 'app.status', + httpMethod: 'get', + httpPath: '/v1/app/status', + }, + { + clientCallName: 'client.app.login.email', + fullyQualifiedName: 'app.login.email', + httpMethod: 'post', + httpPath: '/v1/app/login/email', + }, + { + clientCallName: 'client.app.login.register', + fullyQualifiedName: 'app.login.register', + httpMethod: 'post', + httpPath: '/v1/app/login/register', + }, + { + clientCallName: 'client.app.login.response', + fullyQualifiedName: 'app.login.response', + httpMethod: 'post', + httpPath: '/v1/app/login/response', + }, + { + clientCallName: 'client.app.login.start', + fullyQualifiedName: 'app.login.start', + httpMethod: 'post', + httpPath: '/v1/app/login/start', + }, + { + clientCallName: 'client.app.e2ee.recoveryCode.markBackedUp', + fullyQualifiedName: 'app.e2ee.recoveryCode.markBackedUp', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/recovery-code/mark-backed-up', + }, + { + clientCallName: 'client.app.e2ee.recoveryCode.verify', + fullyQualifiedName: 'app.e2ee.recoveryCode.verify', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/recovery-code/verify', + }, + { + clientCallName: 'client.app.e2ee.recoveryCode.reset.create', + fullyQualifiedName: 'app.e2ee.recoveryCode.reset.create', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/recovery-code/reset', + }, + { + clientCallName: 'client.app.e2ee.recoveryCode.reset.confirm', + fullyQualifiedName: 'app.e2ee.recoveryCode.reset.confirm', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/recovery-code/reset/confirm', + }, + { + clientCallName: 'client.app.e2ee.verification.create', + fullyQualifiedName: 'app.e2ee.verification.create', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/verification', + }, + { + clientCallName: 'client.app.e2ee.verification.accept', + fullyQualifiedName: 'app.e2ee.verification.accept', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/verification/{verificationID}/accept', + }, + { + clientCallName: 'client.app.e2ee.verification.cancel', + fullyQualifiedName: 'app.e2ee.verification.cancel', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/verification/{verificationID}/cancel', + }, + { + clientCallName: 'client.app.e2ee.verification.qr.confirmScanned', + fullyQualifiedName: 'app.e2ee.verification.qr.confirmScanned', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned', + }, + { + clientCallName: 'client.app.e2ee.verification.qr.scan', + fullyQualifiedName: 'app.e2ee.verification.qr.scan', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/verification/qr/scan', + }, + { + clientCallName: 'client.app.e2ee.verification.sas.confirm', + fullyQualifiedName: 'app.e2ee.verification.sas.confirm', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/verification/{verificationID}/sas/confirm', + }, + { + clientCallName: 'client.app.e2ee.verification.sas.start', + fullyQualifiedName: 'app.e2ee.verification.sas.start', + httpMethod: 'post', + httpPath: '/v1/app/e2ee/verification/{verificationID}/sas/start', + }, { clientCallName: 'client.accounts.list', fullyQualifiedName: 'accounts.list', @@ -40,6 +136,169 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/v1/accounts/{accountID}/contacts', }, + { + clientCallName: 'client.bridges.list', + fullyQualifiedName: 'bridges.list', + httpMethod: 'get', + httpPath: '/v1/bridges', + }, + { + clientCallName: 'client.matrix.users.retrieveProfile', + fullyQualifiedName: 'matrix.users.retrieveProfile', + httpMethod: 'get', + httpPath: '/_matrix/client/v3/profile/{userId}', + }, + { + clientCallName: 'client.matrix.users.accountData.retrieve', + fullyQualifiedName: 'matrix.users.accountData.retrieve', + httpMethod: 'get', + httpPath: '/_matrix/client/v3/user/{userId}/account_data/{type}', + }, + { + clientCallName: 'client.matrix.users.accountData.update', + fullyQualifiedName: 'matrix.users.accountData.update', + httpMethod: 'put', + httpPath: '/_matrix/client/v3/user/{userId}/account_data/{type}', + }, + { + clientCallName: 'client.matrix.rooms.create', + fullyQualifiedName: 'matrix.rooms.create', + httpMethod: 'post', + httpPath: '/_matrix/client/v3/createRoom', + }, + { + clientCallName: 'client.matrix.rooms.join', + fullyQualifiedName: 'matrix.rooms.join', + httpMethod: 'post', + httpPath: '/_matrix/client/v3/join/{roomIdOrAlias}', + }, + { + clientCallName: 'client.matrix.rooms.leave', + fullyQualifiedName: 'matrix.rooms.leave', + httpMethod: 'post', + httpPath: '/_matrix/client/v3/rooms/{roomId}/leave', + }, + { + clientCallName: 'client.matrix.rooms.accountData.retrieve', + fullyQualifiedName: 'matrix.rooms.accountData.retrieve', + httpMethod: 'get', + httpPath: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', + }, + { + clientCallName: 'client.matrix.rooms.accountData.update', + fullyQualifiedName: 'matrix.rooms.accountData.update', + httpMethod: 'put', + httpPath: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', + }, + { + clientCallName: 'client.matrix.rooms.state.retrieve', + fullyQualifiedName: 'matrix.rooms.state.retrieve', + httpMethod: 'get', + httpPath: '/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}', + }, + { + clientCallName: 'client.matrix.rooms.state.list', + fullyQualifiedName: 'matrix.rooms.state.list', + httpMethod: 'get', + httpPath: '/_matrix/client/v3/rooms/{roomId}/state', + }, + { + clientCallName: 'client.matrix.rooms.events.retrieve', + fullyQualifiedName: 'matrix.rooms.events.retrieve', + httpMethod: 'get', + httpPath: '/_matrix/client/v3/rooms/{roomId}/event/{eventId}', + }, + { + clientCallName: 'client.matrix.bridges.auth.listFlows', + fullyQualifiedName: 'matrix.bridges.auth.listFlows', + httpMethod: 'get', + httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows', + }, + { + clientCallName: 'client.matrix.bridges.auth.listLogins', + fullyQualifiedName: 'matrix.bridges.auth.listLogins', + httpMethod: 'get', + httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins', + }, + { + clientCallName: 'client.matrix.bridges.auth.logout', + fullyQualifiedName: 'matrix.bridges.auth.logout', + httpMethod: 'post', + httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}', + }, + { + clientCallName: 'client.matrix.bridges.auth.startLogin', + fullyQualifiedName: 'matrix.bridges.auth.startLogin', + httpMethod: 'post', + httpPath: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}', + }, + { + clientCallName: 'client.matrix.bridges.auth.submitCookies', + fullyQualifiedName: 'matrix.bridges.auth.submitCookies', + httpMethod: 'post', + httpPath: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies', + }, + { + clientCallName: 'client.matrix.bridges.auth.submitUserInput', + fullyQualifiedName: 'matrix.bridges.auth.submitUserInput', + httpMethod: 'post', + httpPath: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input', + }, + { + clientCallName: 'client.matrix.bridges.auth.waitForStep', + fullyQualifiedName: 'matrix.bridges.auth.waitForStep', + httpMethod: 'post', + httpPath: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait', + }, + { + clientCallName: 'client.matrix.bridges.auth.whoami', + fullyQualifiedName: 'matrix.bridges.auth.whoami', + httpMethod: 'get', + httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami', + }, + { + clientCallName: 'client.matrix.bridges.contacts.list', + fullyQualifiedName: 'matrix.bridges.contacts.list', + httpMethod: 'get', + httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts', + }, + { + clientCallName: 'client.matrix.bridges.users.resolve', + fullyQualifiedName: 'matrix.bridges.users.resolve', + httpMethod: 'get', + httpPath: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}', + }, + { + clientCallName: 'client.matrix.bridges.users.search', + fullyQualifiedName: 'matrix.bridges.users.search', + httpMethod: 'post', + httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users', + }, + { + clientCallName: 'client.matrix.bridges.rooms.createDm', + fullyQualifiedName: 'matrix.bridges.rooms.createDm', + httpMethod: 'post', + httpPath: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}', + }, + { + clientCallName: 'client.matrix.bridges.rooms.createGroup', + fullyQualifiedName: 'matrix.bridges.rooms.createGroup', + httpMethod: 'post', + httpPath: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}', + }, + { + clientCallName: 'client.matrix.bridges.capabilities.retrieve', + fullyQualifiedName: 'matrix.bridges.capabilities.retrieve', + httpMethod: 'get', + httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities', + }, { clientCallName: 'client.chats.create', fullyQualifiedName: 'chats.create', diff --git a/src/client.ts b/src/client.ts index 90ff33ed..efaa2a81 100644 --- a/src/client.ts +++ b/src/client.ts @@ -37,6 +37,7 @@ import { AssetUploadResponse, Assets, } from './resources/assets'; +import { BridgeAvailability, BridgeListResponse, Bridges } from './resources/bridges'; import { Info, InfoRetrieveResponse } from './resources/info'; import { MessageDeleteParams, @@ -50,6 +51,16 @@ import { Messages, } from './resources/messages'; import { Account, AccountListResponse, Accounts } from './resources/accounts/accounts'; +import { + App, + AppStatusResponse, + LoginRegistrationRequiredResponse, + LoginResponse, + LoginResponseOutput, + RecoveryCodeResetResponse, + StartVerificationResponse, + StateMutationResponse, +} from './resources/app/app'; import { Chat, ChatArchiveParams, @@ -69,6 +80,7 @@ import { Chats, ChatsCursorSearch, } from './resources/chats/chats'; +import { Matrix } from './resources/matrix/matrix'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -845,10 +857,22 @@ export class BeeperDesktop extends BaseBeeperDesktop { static toFile = Uploads.toFile; + /** + * Manage Beeper app login and encrypted messaging setup + */ + app: API.App = new API.App(this); /** * Manage connected chat accounts */ accounts: API.Accounts = new API.Accounts(this); + /** + * Manage bridge-backed account types and account availability + */ + bridges: API.Bridges = new API.Bridges(this); + /** + * Matrix-compatible APIs for accounts, rooms, and connected network bridges. + */ + matrix: API.Matrix = new API.Matrix(this); /** * Manage chats */ @@ -867,7 +891,10 @@ export class BeeperDesktop extends BaseBeeperDesktop { info: API.Info = new API.Info(this); } +BeeperDesktop.App = App; BeeperDesktop.Accounts = Accounts; +BeeperDesktop.Bridges = Bridges; +BeeperDesktop.Matrix = Matrix; BeeperDesktop.Chats = Chats; BeeperDesktop.Messages = Messages; BeeperDesktop.Assets = Assets; @@ -892,8 +919,27 @@ export declare namespace BeeperDesktop { type SearchParams as SearchParams, }; + export { + App as App, + type LoginRegistrationRequiredResponse as LoginRegistrationRequiredResponse, + type LoginResponse as LoginResponse, + type LoginResponseOutput as LoginResponseOutput, + type RecoveryCodeResetResponse as RecoveryCodeResetResponse, + type StartVerificationResponse as StartVerificationResponse, + type StateMutationResponse as StateMutationResponse, + type AppStatusResponse as AppStatusResponse, + }; + export { Accounts as Accounts, type Account as Account, type AccountListResponse as AccountListResponse }; + export { + Bridges as Bridges, + type BridgeAvailability as BridgeAvailability, + type BridgeListResponse as BridgeListResponse, + }; + + export { Matrix as Matrix }; + export { Chats as Chats, type Chat as Chat, @@ -939,6 +985,7 @@ export declare namespace BeeperDesktop { export { Info as Info, type InfoRetrieveResponse as InfoRetrieveResponse }; + export type AppStateSnapshot = API.AppStateSnapshot; export type Attachment = API.Attachment; export type Error = API.Error; export type Message = API.Message; diff --git a/src/resources/app.ts b/src/resources/app.ts new file mode 100644 index 00000000..eed68d32 --- /dev/null +++ b/src/resources/app.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './app/index'; diff --git a/src/resources/app/app.ts b/src/resources/app/app.ts new file mode 100644 index 00000000..c102038f --- /dev/null +++ b/src/resources/app/app.ts @@ -0,0 +1,1727 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as LoginAPI from './login'; +import { + BaseLogin, + Login, + LoginEmailParams, + LoginEmailResponse, + LoginRegisterParams, + LoginRegisterResponse, + LoginResponseParams, + LoginResponseResponse, + LoginStartResponse, +} from './login'; +import * as E2eeAPI from './e2ee/e2ee'; +import { BaseE2ee, E2ee as E2eeAPIE2ee } from './e2ee/e2ee'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +/** + * Manage Beeper app login and encrypted messaging setup + */ +export class BaseApp extends APIResource { + static override readonly _key: readonly ['app'] = Object.freeze(['app'] as const); + + /** + * Return the current Beeper Desktop sign-in and encrypted messaging setup state. + * This endpoint is public before sign-in so apps can discover that login is + * needed; after sign-in, pass a read token. + */ + status(options?: RequestOptions): APIPromise { + return this._client.get('/v1/app/status', options); + } +} +/** + * Manage Beeper app login and encrypted messaging setup + */ +export class App extends BaseApp { + login: LoginAPI.Login = new LoginAPI.Login(this._client); + e2ee: E2eeAPI.E2ee = new E2eeAPI.E2ee(this._client); +} + +export interface LoginRegistrationRequiredResponse { + /** + * Copy to display during account creation. + */ + copy: LoginRegistrationRequiredResponse.Copy; + + /** + * Registration token returned by Beeper. + */ + leadToken: string; + + /** + * Indicates that the user needs to create a Beeper account. + */ + registrationRequired: true; + + /** + * Login request ID to use when creating the account. + */ + request: string; + + /** + * Suggested usernames for the new account. + */ + usernameSuggestions?: Array; +} + +export namespace LoginRegistrationRequiredResponse { + /** + * Copy to display during account creation. + */ + export interface Copy { + /** + * Submit button label. + */ + submit: 'Continue'; + + /** + * Terms and privacy notice to show before account creation. + */ + terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; + + /** + * Title for the username step. + */ + title: 'Choose your username'; + + /** + * Placeholder for the username field. + */ + usernamePlaceholder: 'Username'; + } +} + +export interface LoginResponse { + /** + * Current onboarding state after sign-in. + */ + appState: LoginResponse.AppState; + + /** + * Desktop API credentials for the signed-in app session. + */ + desktopAPI: LoginResponse.DesktopAPI; + + /** + * Account credentials for first-party app setup. + */ + matrix: LoginResponse.Matrix; +} + +export namespace LoginResponse { + /** + * Current onboarding state after sign-in. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } + + /** + * Desktop API credentials for the signed-in app session. + */ + export interface DesktopAPI { + /** + * Desktop API access token for this app session. + */ + accessToken: string; + + /** + * Granted Desktop API scopes. + */ + scope: 'read write'; + + /** + * Access token type. + */ + tokenType: 'Bearer'; + } + + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } +} + +export type LoginResponseOutput = LoginResponseOutput.UnionMember0 | LoginResponseOutput.UnionMember1; + +export namespace LoginResponseOutput { + export interface UnionMember0 { + /** + * Current onboarding state after sign-in. + */ + appState: UnionMember0.AppState; + + /** + * Desktop API credentials for the signed-in app session. + */ + desktopAPI: UnionMember0.DesktopAPI; + + /** + * Account credentials for first-party app setup. + */ + matrix: UnionMember0.Matrix; + } + + export namespace UnionMember0 { + /** + * Current onboarding state after sign-in. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } + + /** + * Desktop API credentials for the signed-in app session. + */ + export interface DesktopAPI { + /** + * Desktop API access token for this app session. + */ + accessToken: string; + + /** + * Granted Desktop API scopes. + */ + scope: 'read write'; + + /** + * Access token type. + */ + tokenType: 'Bearer'; + } + + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + } + + export interface UnionMember1 { + /** + * Copy to display during account creation. + */ + copy: UnionMember1.Copy; + + /** + * Registration token returned by Beeper. + */ + leadToken: string; + + /** + * Indicates that the user needs to create a Beeper account. + */ + registrationRequired: true; + + /** + * Login request ID to use when creating the account. + */ + request: string; + + /** + * Suggested usernames for the new account. + */ + usernameSuggestions?: Array; + } + + export namespace UnionMember1 { + /** + * Copy to display during account creation. + */ + export interface Copy { + /** + * Submit button label. + */ + submit: 'Continue'; + + /** + * Terms and privacy notice to show before account creation. + */ + terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; + + /** + * Title for the username step. + */ + title: 'Choose your username'; + + /** + * Placeholder for the username field. + */ + usernamePlaceholder: 'Username'; + } + } +} + +export interface RecoveryCodeResetResponse { + /** + * Current onboarding state after creating the new recovery key. + */ + appState: RecoveryCodeResetResponse.AppState; + + /** + * New recovery key. Show it once and ask the user to save it. + */ + recoveryCode: string; +} + +export namespace RecoveryCodeResetResponse { + /** + * Current onboarding state after creating the new recovery key. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface StartVerificationResponse { + /** + * Current onboarding state after starting verification. + */ + appState: StartVerificationResponse.AppState; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID: string; +} + +export namespace StartVerificationResponse { + /** + * Current onboarding state after starting verification. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface StateMutationResponse { + /** + * Current onboarding state after the requested step. + */ + appState: StateMutationResponse.AppState; +} + +export namespace StateMutationResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface AppStatusResponse { + /** + * Encrypted messaging setup status. + */ + e2ee: AppStatusResponse.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppStatusResponse.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppStatusResponse.Verification; +} + +export namespace AppStatusResponse { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } +} + +App.Login = Login; +App.BaseLogin = BaseLogin; +App.E2ee = E2eeAPIE2ee; +App.BaseE2ee = BaseE2ee; + +export declare namespace App { + export { + type LoginRegistrationRequiredResponse as LoginRegistrationRequiredResponse, + type LoginResponse as LoginResponse, + type LoginResponseOutput as LoginResponseOutput, + type RecoveryCodeResetResponse as RecoveryCodeResetResponse, + type StartVerificationResponse as StartVerificationResponse, + type StateMutationResponse as StateMutationResponse, + type AppStatusResponse as AppStatusResponse, + }; + + export { + Login as Login, + BaseLogin as BaseLogin, + type LoginEmailResponse as LoginEmailResponse, + type LoginRegisterResponse as LoginRegisterResponse, + type LoginResponseResponse as LoginResponseResponse, + type LoginStartResponse as LoginStartResponse, + type LoginEmailParams as LoginEmailParams, + type LoginRegisterParams as LoginRegisterParams, + type LoginResponseParams as LoginResponseParams, + }; + + export { E2eeAPIE2ee as E2ee, BaseE2ee as BaseE2ee }; +} diff --git a/src/resources/app/e2ee.ts b/src/resources/app/e2ee.ts new file mode 100644 index 00000000..b8f9ae3a --- /dev/null +++ b/src/resources/app/e2ee.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './e2ee/index'; diff --git a/src/resources/app/e2ee/e2ee.ts b/src/resources/app/e2ee/e2ee.ts new file mode 100644 index 00000000..20e3bd3f --- /dev/null +++ b/src/resources/app/e2ee/e2ee.ts @@ -0,0 +1,60 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as RecoveryCodeAPI from './recovery-code/recovery-code'; +import { + BaseRecoveryCode, + RecoveryCode, + RecoveryCodeMarkBackedUpResponse, + RecoveryCodeVerifyParams, + RecoveryCodeVerifyResponse, +} from './recovery-code/recovery-code'; +import * as VerificationAPI from './verification/verification'; +import { + BaseVerification, + Verification, + VerificationAcceptResponse, + VerificationCancelParams, + VerificationCancelResponse, + VerificationCreateParams, + VerificationCreateResponse, +} from './verification/verification'; + +/** + * Manage encrypted messaging setup + */ +export class BaseE2ee extends APIResource { + static override readonly _key: readonly ['app', 'e2ee'] = Object.freeze(['app', 'e2ee'] as const); +} +/** + * Manage encrypted messaging setup + */ +export class E2ee extends BaseE2ee { + recoveryCode: RecoveryCodeAPI.RecoveryCode = new RecoveryCodeAPI.RecoveryCode(this._client); + verification: VerificationAPI.Verification = new VerificationAPI.Verification(this._client); +} + +E2ee.RecoveryCode = RecoveryCode; +E2ee.BaseRecoveryCode = BaseRecoveryCode; +E2ee.Verification = Verification; +E2ee.BaseVerification = BaseVerification; + +export declare namespace E2ee { + export { + RecoveryCode as RecoveryCode, + BaseRecoveryCode as BaseRecoveryCode, + type RecoveryCodeMarkBackedUpResponse as RecoveryCodeMarkBackedUpResponse, + type RecoveryCodeVerifyResponse as RecoveryCodeVerifyResponse, + type RecoveryCodeVerifyParams as RecoveryCodeVerifyParams, + }; + + export { + Verification as Verification, + BaseVerification as BaseVerification, + type VerificationCreateResponse as VerificationCreateResponse, + type VerificationAcceptResponse as VerificationAcceptResponse, + type VerificationCancelResponse as VerificationCancelResponse, + type VerificationCreateParams as VerificationCreateParams, + type VerificationCancelParams as VerificationCancelParams, + }; +} diff --git a/src/resources/app/e2ee/index.ts b/src/resources/app/e2ee/index.ts new file mode 100644 index 00000000..13196e0a --- /dev/null +++ b/src/resources/app/e2ee/index.ts @@ -0,0 +1,19 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { E2ee, BaseE2ee } from './e2ee'; +export { + RecoveryCode, + BaseRecoveryCode, + type RecoveryCodeMarkBackedUpResponse, + type RecoveryCodeVerifyResponse, + type RecoveryCodeVerifyParams, +} from './recovery-code/index'; +export { + Verification, + BaseVerification, + type VerificationCreateResponse, + type VerificationAcceptResponse, + type VerificationCancelResponse, + type VerificationCreateParams, + type VerificationCancelParams, +} from './verification/index'; diff --git a/src/resources/app/e2ee/recovery-code.ts b/src/resources/app/e2ee/recovery-code.ts new file mode 100644 index 00000000..36813bdb --- /dev/null +++ b/src/resources/app/e2ee/recovery-code.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './recovery-code/index'; diff --git a/src/resources/app/e2ee/recovery-code/index.ts b/src/resources/app/e2ee/recovery-code/index.ts new file mode 100644 index 00000000..d51bd744 --- /dev/null +++ b/src/resources/app/e2ee/recovery-code/index.ts @@ -0,0 +1,17 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + RecoveryCode, + BaseRecoveryCode, + type RecoveryCodeMarkBackedUpResponse, + type RecoveryCodeVerifyResponse, + type RecoveryCodeVerifyParams, +} from './recovery-code'; +export { + Reset, + BaseReset, + type ResetCreateResponse, + type ResetConfirmResponse, + type ResetCreateParams, + type ResetConfirmParams, +} from './reset'; diff --git a/src/resources/app/e2ee/recovery-code/recovery-code.ts b/src/resources/app/e2ee/recovery-code/recovery-code.ts new file mode 100644 index 00000000..bfe4dd6d --- /dev/null +++ b/src/resources/app/e2ee/recovery-code/recovery-code.ts @@ -0,0 +1,550 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../../core/resource'; +import * as ResetAPI from './reset'; +import { + BaseReset, + Reset, + ResetConfirmParams, + ResetConfirmResponse, + ResetCreateParams, + ResetCreateResponse, +} from './reset'; +import { APIPromise } from '../../../../core/api-promise'; +import { RequestOptions } from '../../../../internal/request-options'; + +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class BaseRecoveryCode extends APIResource { + static override readonly _key: readonly ['app', 'e2ee', 'recoveryCode'] = Object.freeze([ + 'app', + 'e2ee', + 'recoveryCode', + ] as const); + + /** + * Record that the user saved their recovery key. + */ + markBackedUp(options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/e2ee/recovery-code/mark-backed-up', options); + } + + /** + * Unlock encrypted messages with the user recovery key. + */ + verify(body: RecoveryCodeVerifyParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/e2ee/recovery-code/verify', { body, ...options }); + } +} +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class RecoveryCode extends BaseRecoveryCode { + reset: ResetAPI.Reset = new ResetAPI.Reset(this._client); +} + +export interface RecoveryCodeMarkBackedUpResponse { + /** + * Current onboarding state after the requested step. + */ + appState: RecoveryCodeMarkBackedUpResponse.AppState; +} + +export namespace RecoveryCodeMarkBackedUpResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface RecoveryCodeVerifyResponse { + /** + * Current onboarding state after the requested step. + */ + appState: RecoveryCodeVerifyResponse.AppState; +} + +export namespace RecoveryCodeVerifyResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface RecoveryCodeVerifyParams { + /** + * Recovery key saved by the user. + */ + recoveryCode: string; +} + +RecoveryCode.Reset = Reset; +RecoveryCode.BaseReset = BaseReset; + +export declare namespace RecoveryCode { + export { + type RecoveryCodeMarkBackedUpResponse as RecoveryCodeMarkBackedUpResponse, + type RecoveryCodeVerifyResponse as RecoveryCodeVerifyResponse, + type RecoveryCodeVerifyParams as RecoveryCodeVerifyParams, + }; + + export { + Reset as Reset, + BaseReset as BaseReset, + type ResetCreateResponse as ResetCreateResponse, + type ResetConfirmResponse as ResetConfirmResponse, + type ResetCreateParams as ResetCreateParams, + type ResetConfirmParams as ResetConfirmParams, + }; +} diff --git a/src/resources/app/e2ee/recovery-code/reset.ts b/src/resources/app/e2ee/recovery-code/reset.ts new file mode 100644 index 00000000..d8e64f9b --- /dev/null +++ b/src/resources/app/e2ee/recovery-code/reset.ts @@ -0,0 +1,544 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../../core/resource'; +import { APIPromise } from '../../../../core/api-promise'; +import { RequestOptions } from '../../../../internal/request-options'; + +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class BaseReset extends APIResource { + static override readonly _key: readonly ['app', 'e2ee', 'recoveryCode', 'reset'] = Object.freeze([ + 'app', + 'e2ee', + 'recoveryCode', + 'reset', + ] as const); + + /** + * Create a new recovery key when the user cannot use the existing one. + */ + create( + body: ResetCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/v1/app/e2ee/recovery-code/reset', { body, ...options }); + } + + /** + * Confirm that the new recovery key should be used for this account. + */ + confirm(body: ResetConfirmParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/e2ee/recovery-code/reset/confirm', { body, ...options }); + } +} +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class Reset extends BaseReset {} + +export interface ResetCreateResponse { + /** + * Current onboarding state after creating the new recovery key. + */ + appState: ResetCreateResponse.AppState; + + /** + * New recovery key. Show it once and ask the user to save it. + */ + recoveryCode: string; +} + +export namespace ResetCreateResponse { + /** + * Current onboarding state after creating the new recovery key. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface ResetConfirmResponse { + /** + * Current onboarding state after the requested step. + */ + appState: ResetConfirmResponse.AppState; +} + +export namespace ResetConfirmResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface ResetCreateParams { + /** + * Existing recovery key, if the user has it. + */ + recoveryCode?: string; +} + +export interface ResetConfirmParams { + /** + * New recovery key returned by the reset step. + */ + recoveryCode: string; +} + +export declare namespace Reset { + export { + type ResetCreateResponse as ResetCreateResponse, + type ResetConfirmResponse as ResetConfirmResponse, + type ResetCreateParams as ResetCreateParams, + type ResetConfirmParams as ResetConfirmParams, + }; +} diff --git a/src/resources/app/e2ee/verification.ts b/src/resources/app/e2ee/verification.ts new file mode 100644 index 00000000..d46fce2b --- /dev/null +++ b/src/resources/app/e2ee/verification.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './verification/index'; diff --git a/src/resources/app/e2ee/verification/index.ts b/src/resources/app/e2ee/verification/index.ts new file mode 100644 index 00000000..579206f3 --- /dev/null +++ b/src/resources/app/e2ee/verification/index.ts @@ -0,0 +1,13 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Qr, BaseQr, type QrConfirmScannedResponse, type QrScanResponse, type QrScanParams } from './qr'; +export { Sas, BaseSas, type SaConfirmResponse, type SaStartResponse } from './sas'; +export { + Verification, + BaseVerification, + type VerificationCreateResponse, + type VerificationAcceptResponse, + type VerificationCancelResponse, + type VerificationCreateParams, + type VerificationCancelParams, +} from './verification'; diff --git a/src/resources/app/e2ee/verification/qr.ts b/src/resources/app/e2ee/verification/qr.ts new file mode 100644 index 00000000..dc31dfdd --- /dev/null +++ b/src/resources/app/e2ee/verification/qr.ts @@ -0,0 +1,529 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../../core/resource'; +import { APIPromise } from '../../../../core/api-promise'; +import { RequestOptions } from '../../../../internal/request-options'; +import { path } from '../../../../internal/utils/path'; + +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class BaseQr extends APIResource { + static override readonly _key: readonly ['app', 'e2ee', 'verification', 'qr'] = Object.freeze([ + 'app', + 'e2ee', + 'verification', + 'qr', + ] as const); + + /** + * Confirm that another device scanned this device QR code. + */ + confirmScanned(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/qr/confirm-scanned`, options); + } + + /** + * Submit the QR code scanned from another signed-in device. + */ + scan(body: QrScanParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/e2ee/verification/qr/scan', { body, ...options }); + } +} +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class Qr extends BaseQr {} + +export interface QrConfirmScannedResponse { + /** + * Current onboarding state after the requested step. + */ + appState: QrConfirmScannedResponse.AppState; +} + +export namespace QrConfirmScannedResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface QrScanResponse { + /** + * Current onboarding state after the requested step. + */ + appState: QrScanResponse.AppState; +} + +export namespace QrScanResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface QrScanParams { + /** + * QR code payload scanned from the other device. + */ + data: string; +} + +export declare namespace Qr { + export { + type QrConfirmScannedResponse as QrConfirmScannedResponse, + type QrScanResponse as QrScanResponse, + type QrScanParams as QrScanParams, + }; +} diff --git a/src/resources/app/e2ee/verification/sas.ts b/src/resources/app/e2ee/verification/sas.ts new file mode 100644 index 00000000..5470c77b --- /dev/null +++ b/src/resources/app/e2ee/verification/sas.ts @@ -0,0 +1,518 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../../core/resource'; +import { APIPromise } from '../../../../core/api-promise'; +import { RequestOptions } from '../../../../internal/request-options'; +import { path } from '../../../../internal/utils/path'; + +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class BaseSas extends APIResource { + static override readonly _key: readonly ['app', 'e2ee', 'verification', 'sas'] = Object.freeze([ + 'app', + 'e2ee', + 'verification', + 'sas', + ] as const); + + /** + * Confirm that the emoji or number sequence matches on both devices. + */ + confirm(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/sas/confirm`, options); + } + + /** + * Start emoji comparison for device verification. + */ + start(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/sas/start`, options); + } +} +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class Sas extends BaseSas {} + +export interface SaConfirmResponse { + /** + * Current onboarding state after the requested step. + */ + appState: SaConfirmResponse.AppState; +} + +export namespace SaConfirmResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface SaStartResponse { + /** + * Current onboarding state after the requested step. + */ + appState: SaStartResponse.AppState; +} + +export namespace SaStartResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export declare namespace Sas { + export { type SaConfirmResponse as SaConfirmResponse, type SaStartResponse as SaStartResponse }; +} diff --git a/src/resources/app/e2ee/verification/verification.ts b/src/resources/app/e2ee/verification/verification.ts new file mode 100644 index 00000000..38c6f5b7 --- /dev/null +++ b/src/resources/app/e2ee/verification/verification.ts @@ -0,0 +1,827 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../../core/resource'; +import * as QrAPI from './qr'; +import { BaseQr, Qr, QrConfirmScannedResponse, QrScanParams, QrScanResponse } from './qr'; +import * as SasAPI from './sas'; +import { BaseSas, SaConfirmResponse, SaStartResponse, Sas as SasAPISas } from './sas'; +import { APIPromise } from '../../../../core/api-promise'; +import { RequestOptions } from '../../../../internal/request-options'; +import { path } from '../../../../internal/utils/path'; + +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class BaseVerification extends APIResource { + static override readonly _key: readonly ['app', 'e2ee', 'verification'] = Object.freeze([ + 'app', + 'e2ee', + 'verification', + ] as const); + + /** + * Start verifying this device from another signed-in device. + */ + create( + body: VerificationCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/v1/app/e2ee/verification', { body, ...options }); + } + + /** + * Accept an incoming device verification request. + */ + accept(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/accept`, options); + } + + /** + * Cancel an active device verification request. + */ + cancel( + verificationID: string, + body: VerificationCancelParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/cancel`, { body, ...options }); + } +} +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class Verification extends BaseVerification { + qr: QrAPI.Qr = new QrAPI.Qr(this._client); + sas: SasAPI.Sas = new SasAPI.Sas(this._client); +} + +export interface VerificationCreateResponse { + /** + * Current onboarding state after starting verification. + */ + appState: VerificationCreateResponse.AppState; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID: string; +} + +export namespace VerificationCreateResponse { + /** + * Current onboarding state after starting verification. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface VerificationAcceptResponse { + /** + * Current onboarding state after the requested step. + */ + appState: VerificationAcceptResponse.AppState; +} + +export namespace VerificationAcceptResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface VerificationCancelResponse { + /** + * Current onboarding state after the requested step. + */ + appState: VerificationCancelResponse.AppState; +} + +export namespace VerificationCancelResponse { + /** + * Current onboarding state after the requested step. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } +} + +export interface VerificationCreateParams { + /** + * User ID to verify. Defaults to the signed-in user. + */ + userID?: string; +} + +export interface VerificationCancelParams { + /** + * Optional cancellation code. + */ + code?: string; + + /** + * Optional user-facing cancellation reason. + */ + reason?: string; +} + +Verification.Qr = Qr; +Verification.BaseQr = BaseQr; +Verification.Sas = SasAPISas; +Verification.BaseSas = BaseSas; + +export declare namespace Verification { + export { + type VerificationCreateResponse as VerificationCreateResponse, + type VerificationAcceptResponse as VerificationAcceptResponse, + type VerificationCancelResponse as VerificationCancelResponse, + type VerificationCreateParams as VerificationCreateParams, + type VerificationCancelParams as VerificationCancelParams, + }; + + export { + Qr as Qr, + BaseQr as BaseQr, + type QrConfirmScannedResponse as QrConfirmScannedResponse, + type QrScanResponse as QrScanResponse, + type QrScanParams as QrScanParams, + }; + + export { + SasAPISas as Sas, + BaseSas as BaseSas, + type SaConfirmResponse as SaConfirmResponse, + type SaStartResponse as SaStartResponse, + }; +} diff --git a/src/resources/app/index.ts b/src/resources/app/index.ts new file mode 100644 index 00000000..22a33530 --- /dev/null +++ b/src/resources/app/index.ts @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + App, + BaseApp, + type LoginRegistrationRequiredResponse, + type LoginResponse, + type LoginResponseOutput, + type RecoveryCodeResetResponse, + type StartVerificationResponse, + type StateMutationResponse, + type AppStatusResponse, +} from './app'; +export { E2ee, BaseE2ee } from './e2ee/index'; +export { + Login, + BaseLogin, + type LoginEmailResponse, + type LoginRegisterResponse, + type LoginResponseResponse, + type LoginStartResponse, + type LoginEmailParams, + type LoginRegisterParams, + type LoginResponseParams, +} from './login'; diff --git a/src/resources/app/login.ts b/src/resources/app/login.ts new file mode 100644 index 00000000..ce2c7b79 --- /dev/null +++ b/src/resources/app/login.ts @@ -0,0 +1,766 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; + +/** + * Complete first-party Beeper app login + */ +export class BaseLogin extends APIResource { + static override readonly _key: readonly ['app', 'login'] = Object.freeze(['app', 'login'] as const); + + /** + * Send a sign-in code to the user email address. + */ + email(body: LoginEmailParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/email', { body, ...options, __security: {} }); + } + + /** + * Create a Beeper account after the user chooses a username and accepts the Terms + * of Use. + */ + register(body: LoginRegisterParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/register', { body, ...options, __security: {} }); + } + + /** + * Finish sign-in with the code sent to the user email address. If the user needs a + * new account, the response includes account creation copy and username + * suggestions. + */ + response(body: LoginResponseParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/response', { body, ...options, __security: {} }); + } + + /** + * Start a first-party Beeper Desktop sign-in session. + */ + start(options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/start', { ...options, __security: {} }); + } +} +/** + * Complete first-party Beeper app login + */ +export class Login extends BaseLogin {} + +export type LoginEmailResponse = unknown; + +export interface LoginRegisterResponse { + /** + * Current onboarding state after sign-in. + */ + appState: LoginRegisterResponse.AppState; + + /** + * Desktop API credentials for the signed-in app session. + */ + desktopAPI: LoginRegisterResponse.DesktopAPI; + + /** + * Account credentials for first-party app setup. + */ + matrix: LoginRegisterResponse.Matrix; +} + +export namespace LoginRegisterResponse { + /** + * Current onboarding state after sign-in. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } + + /** + * Desktop API credentials for the signed-in app session. + */ + export interface DesktopAPI { + /** + * Desktop API access token for this app session. + */ + accessToken: string; + + /** + * Granted Desktop API scopes. + */ + scope: 'read write'; + + /** + * Access token type. + */ + tokenType: 'Bearer'; + } + + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } +} + +export type LoginResponseResponse = LoginResponseResponse.UnionMember0 | LoginResponseResponse.UnionMember1; + +export namespace LoginResponseResponse { + export interface UnionMember0 { + /** + * Current onboarding state after sign-in. + */ + appState: UnionMember0.AppState; + + /** + * Desktop API credentials for the signed-in app session. + */ + desktopAPI: UnionMember0.DesktopAPI; + + /** + * Account credentials for first-party app setup. + */ + matrix: UnionMember0.Matrix; + } + + export namespace UnionMember0 { + /** + * Current onboarding state after sign-in. + */ + export interface AppState { + /** + * Encrypted messaging setup status. + */ + e2ee: AppState.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppState.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppState.Verification; + } + + export namespace AppState { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } + } + + /** + * Desktop API credentials for the signed-in app session. + */ + export interface DesktopAPI { + /** + * Desktop API access token for this app session. + */ + accessToken: string; + + /** + * Granted Desktop API scopes. + */ + scope: 'read write'; + + /** + * Access token type. + */ + tokenType: 'Bearer'; + } + + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + } + + export interface UnionMember1 { + /** + * Copy to display during account creation. + */ + copy: UnionMember1.Copy; + + /** + * Registration token returned by Beeper. + */ + leadToken: string; + + /** + * Indicates that the user needs to create a Beeper account. + */ + registrationRequired: true; + + /** + * Login request ID to use when creating the account. + */ + request: string; + + /** + * Suggested usernames for the new account. + */ + usernameSuggestions?: Array; + } + + export namespace UnionMember1 { + /** + * Copy to display during account creation. + */ + export interface Copy { + /** + * Submit button label. + */ + submit: 'Continue'; + + /** + * Terms and privacy notice to show before account creation. + */ + terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; + + /** + * Title for the username step. + */ + title: 'Choose your username'; + + /** + * Placeholder for the username field. + */ + usernamePlaceholder: 'Username'; + } + } +} + +export interface LoginStartResponse { + /** + * Login request ID to use in the next sign-in step. + */ + request: string; + + /** + * Available sign-in methods for this request. + */ + type: Array; +} + +export interface LoginEmailParams { + /** + * Email address to send the sign-in code to. + */ + email: string; + + /** + * Login request ID returned by the start step. + */ + request: string; +} + +export interface LoginRegisterParams { + /** + * Confirms that the user accepted the Terms of Use and acknowledged the Privacy + * Policy. + */ + acceptTerms: true; + + /** + * Registration token returned by Beeper. + */ + leadToken: string; + + /** + * Login request ID returned by the start step. + */ + request: string; + + /** + * Username selected by the user. + */ + username: string; +} + +export interface LoginResponseParams { + /** + * Login request ID returned by the start step. + */ + request: string; + + /** + * Sign-in code from the user email. + */ + response: string; +} + +export declare namespace Login { + export { + type LoginEmailResponse as LoginEmailResponse, + type LoginRegisterResponse as LoginRegisterResponse, + type LoginResponseResponse as LoginResponseResponse, + type LoginStartResponse as LoginStartResponse, + type LoginEmailParams as LoginEmailParams, + type LoginRegisterParams as LoginRegisterParams, + type LoginResponseParams as LoginResponseParams, + }; +} diff --git a/src/resources/bridges.ts b/src/resources/bridges.ts new file mode 100644 index 00000000..dc1712c2 --- /dev/null +++ b/src/resources/bridges.ts @@ -0,0 +1,107 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../core/resource'; +import * as AccountsAPI from './accounts/accounts'; +import { APIPromise } from '../core/api-promise'; +import { RequestOptions } from '../internal/request-options'; + +/** + * Manage bridge-backed account types and account availability + */ +export class BaseBridges extends APIResource { + static override readonly _key: readonly ['bridges'] = Object.freeze(['bridges'] as const); + + /** + * List bridge-backed account types that can be shown in add-account flows, grouped + * with connected accounts that use the same Account schema as GET /v1/accounts. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/v1/bridges', options); + } +} +/** + * Manage bridge-backed account types and account availability + */ +export class Bridges extends BaseBridges {} + +/** + * Bridge-backed account type that can be shown in add-account flows. + */ +export interface BridgeAvailability { + /** + * Connected accounts for this bridge. Uses the same Account schema as GET + * /v1/accounts. + */ + accounts: Array; + + /** + * Number of active accounts for this network on this device. + */ + activeAccountCount: number; + + /** + * Bridge metadata for the account. Available in Beeper Desktop v4.2.785+. + */ + bridge: BridgeAvailability.Bridge; + + /** + * Human-friendly account type name shown in Beeper Desktop. + */ + displayName: string; + + /** + * Login mode used by Beeper Desktop for this bridge. + */ + loginMode: string; + + /** + * Whether this bridge can currently be used to add an account. + */ + status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; + + /** + * Network grouping used for account counts and limits. + */ + network?: string; + + /** + * Human-friendly status text matching Beeper Desktop account management language. + */ + statusText?: string; +} + +export namespace BridgeAvailability { + /** + * Bridge metadata for the account. Available in Beeper Desktop v4.2.785+. + */ + export interface Bridge { + /** + * Bridge instance identifier. Matrix and cloud bridges often use the bridge type + * (for example matrix or discordgo); local bridges use a local bridge ID (for + * example local-whatsapp). Available in Beeper Desktop v4.2.785+. + */ + id: string; + + /** + * Bridge provider for the account. Available in Beeper Desktop v4.2.785+. + */ + provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; + + /** + * Bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, or twitter. + * Available in Beeper Desktop v4.2.785+. + */ + type: string; + } +} + +/** + * Bridge-backed account types and their connected accounts. + */ +export interface BridgeListResponse { + items: Array; +} + +export declare namespace Bridges { + export { type BridgeAvailability as BridgeAvailability, type BridgeListResponse as BridgeListResponse }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 7e824186..7f48ccbe 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -2,6 +2,17 @@ export * from './shared'; export { Accounts, BaseAccounts, type Account, type AccountListResponse } from './accounts/accounts'; +export { + App, + BaseApp, + type LoginRegistrationRequiredResponse, + type LoginResponse, + type LoginResponseOutput, + type RecoveryCodeResetResponse, + type StartVerificationResponse, + type StateMutationResponse, + type AppStatusResponse, +} from './app/app'; export { Assets, BaseAssets, @@ -13,6 +24,7 @@ export { type AssetUploadParams, type AssetUploadBase64Params, } from './assets'; +export { Bridges, BaseBridges, type BridgeAvailability, type BridgeListResponse } from './bridges'; export { Chats, BaseChats, @@ -34,6 +46,7 @@ export { type ChatsCursorSearch, } from './chats/chats'; export { Info, BaseInfo, type InfoRetrieveResponse } from './info'; +export { Matrix, BaseMatrix } from './matrix/matrix'; export { Messages, BaseMessages, diff --git a/src/resources/matrix.ts b/src/resources/matrix.ts new file mode 100644 index 00000000..ee5d2cc9 --- /dev/null +++ b/src/resources/matrix.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './matrix/index'; diff --git a/src/resources/matrix/bridges.ts b/src/resources/matrix/bridges.ts new file mode 100644 index 00000000..3a874ef4 --- /dev/null +++ b/src/resources/matrix/bridges.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './bridges/index'; diff --git a/src/resources/matrix/bridges/auth.ts b/src/resources/matrix/bridges/auth.ts new file mode 100644 index 00000000..5d98374c --- /dev/null +++ b/src/resources/matrix/bridges/auth.ts @@ -0,0 +1,1950 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class BaseAuth extends APIResource { + static override readonly _key: readonly ['matrix', 'bridges', 'auth'] = Object.freeze([ + 'matrix', + 'bridges', + 'auth', + ] as const); + + /** + * Get the available login flows. + * + * @example + * ```ts + * const response = await client.matrix.bridges.auth.listFlows( + * 'bridgeID', + * ); + * ``` + */ + listFlows(bridgeID: string, options?: RequestOptions): APIPromise { + return this._client.get( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/flows`, + options, + ); + } + + /** + * Get the login IDs of the current user. + * + * @example + * ```ts + * const response = + * await client.matrix.bridges.auth.listLogins('bridgeID'); + * ``` + */ + listLogins(bridgeID: string, options?: RequestOptions): APIPromise { + return this._client.get( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/logins`, + options, + ); + } + + /** + * Log out of an existing login. + * + * @example + * ```ts + * const response = await client.matrix.bridges.auth.logout( + * 'bcc68892-b180-414f-9516-b4aadf7d0496', + * { bridgeID: 'bridgeID' }, + * ); + * ``` + */ + logout(loginID: string, params: AuthLogoutParams, options?: RequestOptions): APIPromise { + const { bridgeID } = params; + return this._client.post( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/logout/${loginID}`, + options, + ); + } + + /** + * This endpoint starts a new login process, which is used to log into the bridge. + * + * The basic flow of the entire login, including calling this endpoint, is: + * + * 1. Call `GET /v3/login/flows` to get the list of available flows. If there's + * more than one flow, ask the user to pick which one they want to use. + * 2. Call this endpoint with the chosen flow ID to start the login. The first + * login step will be returned. + * 3. Render the information provided in the step. + * 4. Call the `/login/step/...` endpoint corresponding to the step type: + * - For `user_input` and `cookies`, acquire the requested fields before calling + * the endpoint. + * - For `display_and_wait`, call the endpoint immediately (as there's nothing + * to acquire on the client side). + * 5. Handle the data returned by the login step endpoint: + * - If an error is returned, the login has failed and must be restarted (from + * either step 1 or step 2) if the user wants to try again. + * - If step type `complete` is returned, the login finished successfully. + * - Otherwise, go to step 3 with the new data. + * + * @example + * ```ts + * const response = + * await client.matrix.bridges.auth.startLogin('qr', { + * bridgeID: 'bridgeID', + * }); + * ``` + */ + startLogin( + flowID: string, + params: AuthStartLoginParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, login_id } = params; + return this._client.post( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/start/${flowID}`, + { query: { login_id }, ...options }, + ); + } + + /** + * Submit extracted cookies in a login process. + * + * @example + * ```ts + * const response = + * await client.matrix.bridges.auth.submitCookies('stepID', { + * bridgeID: 'bridgeID', + * loginProcessID: 'loginProcessID', + * body: { foo: 'string' }, + * }); + * ``` + */ + submitCookies( + stepID: string, + params: AuthSubmitCookiesParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, loginProcessID, body } = params; + return this._client.post( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/step/${loginProcessID}/${stepID}/cookies`, + { body: body, ...options }, + ); + } + + /** + * Submit user input in a login process. + * + * @example + * ```ts + * const response = + * await client.matrix.bridges.auth.submitUserInput( + * 'stepID', + * { + * bridgeID: 'bridgeID', + * loginProcessID: 'loginProcessID', + * body: { foo: 'string' }, + * }, + * ); + * ``` + */ + submitUserInput( + stepID: string, + params: AuthSubmitUserInputParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, loginProcessID, body } = params; + return this._client.post( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/step/${loginProcessID}/${stepID}/user_input`, + { body: body, ...options }, + ); + } + + /** + * Wait for the next step after displaying data to the user. + * + * @example + * ```ts + * const response = + * await client.matrix.bridges.auth.waitForStep('stepID', { + * bridgeID: 'bridgeID', + * loginProcessID: 'loginProcessID', + * }); + * ``` + */ + waitForStep( + stepID: string, + params: AuthWaitForStepParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, loginProcessID } = params; + return this._client.post( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/step/${loginProcessID}/${stepID}/display_and_wait`, + options, + ); + } + + /** + * Get all info that is useful for presenting this bridge in a manager interface. + * + * - Server details: remote network details, available login flows, homeserver + * name, bridge bot user ID, command prefix + * - User details: management room ID, list of logins with current state and info + * + * @example + * ```ts + * const response = await client.matrix.bridges.auth.whoami( + * 'bridgeID', + * ); + * ``` + */ + whoami(bridgeID: string, options?: RequestOptions): APIPromise { + return this._client.get( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/whoami`, + options, + ); + } +} +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class Auth extends BaseAuth {} + +export interface AuthListFlowsResponse { + flows?: Array; +} + +export namespace AuthListFlowsResponse { + /** + * An individual login flow which can be used to sign into the remote network. + */ + export interface Flow { + /** + * An internal ID that is passed to the /login/start call to start a login with + * this flow. + */ + id: string; + + /** + * A human-readable description of the login flow. + */ + description: string; + + /** + * A human-readable name for the login flow. + */ + name: string; + } +} + +export interface AuthListLoginsResponse { + login_ids?: Array; +} + +/** + * Empty object + */ +export type AuthLogoutResponse = unknown; + +/** + * A step in a login process. + */ +export type AuthStartLoginResponse = + | AuthStartLoginResponse.UnionMember0 + | AuthStartLoginResponse.UnionMember1 + | AuthStartLoginResponse.UnionMember2 + | AuthStartLoginResponse.UnionMember3; + +export namespace AuthStartLoginResponse { + /** + * Display and wait login step + */ + export interface UnionMember0 { + /** + * Parameters for the display and wait login step + */ + display_and_wait: UnionMember0.DisplayAndWait; + + type: 'display_and_wait'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember0 { + /** + * Parameters for the display and wait login step + */ + export interface DisplayAndWait { + /** + * The type of thing to display + */ + type: 'qr' | 'emoji' | 'code' | 'nothing'; + + /** + * The thing to display (raw data for QR, unicode emoji for emoji, plain string for + * code) + */ + data?: string; + + /** + * An image containing the thing to display. If present, this is recommended over + * using data directly. For emojis, the URL to the canonical image representation + * of the emoji + */ + image_url?: string; + } + } + + /** + * User input login step + */ + export interface UnionMember1 { + type: 'user_input'; + + /** + * Parameters for the user input login step + */ + user_input: UnionMember1.UserInput; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember1 { + /** + * Parameters for the user input login step + */ + export interface UserInput { + /** + * The list of fields that the user is requested to fill. + */ + fields: Array; + + /** + * A list of media attachments to show the user alongside the form fields. + */ + attachments?: Array; + } + + export namespace UserInput { + /** + * A field that the user can fill. + */ + export interface Field { + /** + * The internal ID of the field. This must be used as the key in the object when + * submitting the data back to the bridge. + */ + id: string; + + /** + * The name of the field shown to the user. + */ + name: string; + + /** + * The type of field. + */ + type: + | 'username' + | 'phone_number' + | 'email' + | 'password' + | '2fa_code' + | 'token' + | 'url' + | 'domain' + | 'select'; + + /** + * A default value that the client can pre-fill the field with. + */ + default_value?: string; + + /** + * A more detailed description of the field shown to the user. + */ + description?: string; + + /** + * For fields of type select, the valid options. + */ + options?: Array; + + /** + * A regular expression that the field value must match. + */ + pattern?: string; + } + + /** + * A media attachment to show the user. + */ + export interface Attachment { + /** + * The raw file content for the attachment encoded in base64. + */ + content: string; + + /** + * The filename for the media attachment. + */ + filename: string; + + /** + * The type of media attachment, using the same media type identifiers as Matrix + * attachments. Only some are supported. + */ + type: 'm.image' | 'm.audio'; + + /** + * Optional but recommended metadata for the attachment. Can generally be derived + * from the raw content if omitted. + */ + info?: Attachment.Info; + } + + export namespace Attachment { + /** + * Optional but recommended metadata for the attachment. Can generally be derived + * from the raw content if omitted. + */ + export interface Info { + /** + * The height of the media in pixels. Only applicable for images and videos. + */ + h?: number; + + /** + * The MIME type for the media content. + */ + mimetype?: string; + + /** + * The size of the media content in number of bytes. Strongly recommended to + * include. + */ + size?: number; + + /** + * The width of the media in pixels. Only applicable for images and videos. + */ + w?: number; + } + } + } + } + + /** + * Cookie login step + */ + export interface UnionMember2 { + /** + * Parameters for the cookie login step + */ + cookies: UnionMember2.Cookies; + + type: 'cookies'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember2 { + /** + * Parameters for the cookie login step + */ + export interface Cookies { + /** + * The list of cookies or other stored data that must be extracted. + */ + fields: Array; + + /** + * The URL to open when using a webview to extract cookies. + */ + url: string; + + /** + * A JavaScript snippet that can extract some or all of the fields. The snippet + * will evaluate to a promise that resolves when the relevant fields are found. + * Fields that are not present in the promise result must be extracted another way. + */ + extract_js?: string; + + /** + * An optional user agent that the webview should use. + */ + user_agent?: string; + + /** + * A regex pattern that the URL should match before the client closes the webview. + * + * The client may submit the login if the user closes the webview after all cookies + * are collected even if this URL is not reached, but it should only automatically + * close the webview after both cookies and the URL match. + */ + wait_for_url_pattern?: string; + } + + export namespace Cookies { + /** + * An individual cookie or other stored data item that must be extracted. + */ + export interface Field { + /** + * The name of the item to extract. + */ + name: string; + + /** + * The type of data to extract. + */ + type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; + + /** + * For the `cookie` type, the domain of the cookie. + */ + cookie_domain?: string; + + /** + * For the `request_header` and `request_body` types, a regex that matches the URLs + * from which the values can be extracted. + */ + request_url_regex?: string; + } + } + } + + /** + * Login complete + */ + export interface UnionMember3 { + /** + * Information about the completed login + */ + complete: UnionMember3.Complete; + + type: 'complete'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember3 { + /** + * Information about the completed login + */ + export interface Complete { + /** + * The unique ID of a login. Defined by the network connector. + */ + user_login_id?: string; + } + } +} + +/** + * A step in a login process. + */ +export type AuthSubmitCookiesResponse = + | AuthSubmitCookiesResponse.UnionMember0 + | AuthSubmitCookiesResponse.UnionMember1 + | AuthSubmitCookiesResponse.UnionMember2 + | AuthSubmitCookiesResponse.UnionMember3; + +export namespace AuthSubmitCookiesResponse { + /** + * Display and wait login step + */ + export interface UnionMember0 { + /** + * Parameters for the display and wait login step + */ + display_and_wait: UnionMember0.DisplayAndWait; + + type: 'display_and_wait'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember0 { + /** + * Parameters for the display and wait login step + */ + export interface DisplayAndWait { + /** + * The type of thing to display + */ + type: 'qr' | 'emoji' | 'code' | 'nothing'; + + /** + * The thing to display (raw data for QR, unicode emoji for emoji, plain string for + * code) + */ + data?: string; + + /** + * An image containing the thing to display. If present, this is recommended over + * using data directly. For emojis, the URL to the canonical image representation + * of the emoji + */ + image_url?: string; + } + } + + /** + * User input login step + */ + export interface UnionMember1 { + type: 'user_input'; + + /** + * Parameters for the user input login step + */ + user_input: UnionMember1.UserInput; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember1 { + /** + * Parameters for the user input login step + */ + export interface UserInput { + /** + * The list of fields that the user is requested to fill. + */ + fields: Array; + + /** + * A list of media attachments to show the user alongside the form fields. + */ + attachments?: Array; + } + + export namespace UserInput { + /** + * A field that the user can fill. + */ + export interface Field { + /** + * The internal ID of the field. This must be used as the key in the object when + * submitting the data back to the bridge. + */ + id: string; + + /** + * The name of the field shown to the user. + */ + name: string; + + /** + * The type of field. + */ + type: + | 'username' + | 'phone_number' + | 'email' + | 'password' + | '2fa_code' + | 'token' + | 'url' + | 'domain' + | 'select'; + + /** + * A default value that the client can pre-fill the field with. + */ + default_value?: string; + + /** + * A more detailed description of the field shown to the user. + */ + description?: string; + + /** + * For fields of type select, the valid options. + */ + options?: Array; + + /** + * A regular expression that the field value must match. + */ + pattern?: string; + } + + /** + * A media attachment to show the user. + */ + export interface Attachment { + /** + * The raw file content for the attachment encoded in base64. + */ + content: string; + + /** + * The filename for the media attachment. + */ + filename: string; + + /** + * The type of media attachment, using the same media type identifiers as Matrix + * attachments. Only some are supported. + */ + type: 'm.image' | 'm.audio'; + + /** + * Optional but recommended metadata for the attachment. Can generally be derived + * from the raw content if omitted. + */ + info?: Attachment.Info; + } + + export namespace Attachment { + /** + * Optional but recommended metadata for the attachment. Can generally be derived + * from the raw content if omitted. + */ + export interface Info { + /** + * The height of the media in pixels. Only applicable for images and videos. + */ + h?: number; + + /** + * The MIME type for the media content. + */ + mimetype?: string; + + /** + * The size of the media content in number of bytes. Strongly recommended to + * include. + */ + size?: number; + + /** + * The width of the media in pixels. Only applicable for images and videos. + */ + w?: number; + } + } + } + } + + /** + * Cookie login step + */ + export interface UnionMember2 { + /** + * Parameters for the cookie login step + */ + cookies: UnionMember2.Cookies; + + type: 'cookies'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember2 { + /** + * Parameters for the cookie login step + */ + export interface Cookies { + /** + * The list of cookies or other stored data that must be extracted. + */ + fields: Array; + + /** + * The URL to open when using a webview to extract cookies. + */ + url: string; + + /** + * A JavaScript snippet that can extract some or all of the fields. The snippet + * will evaluate to a promise that resolves when the relevant fields are found. + * Fields that are not present in the promise result must be extracted another way. + */ + extract_js?: string; + + /** + * An optional user agent that the webview should use. + */ + user_agent?: string; + + /** + * A regex pattern that the URL should match before the client closes the webview. + * + * The client may submit the login if the user closes the webview after all cookies + * are collected even if this URL is not reached, but it should only automatically + * close the webview after both cookies and the URL match. + */ + wait_for_url_pattern?: string; + } + + export namespace Cookies { + /** + * An individual cookie or other stored data item that must be extracted. + */ + export interface Field { + /** + * The name of the item to extract. + */ + name: string; + + /** + * The type of data to extract. + */ + type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; + + /** + * For the `cookie` type, the domain of the cookie. + */ + cookie_domain?: string; + + /** + * For the `request_header` and `request_body` types, a regex that matches the URLs + * from which the values can be extracted. + */ + request_url_regex?: string; + } + } + } + + /** + * Login complete + */ + export interface UnionMember3 { + /** + * Information about the completed login + */ + complete: UnionMember3.Complete; + + type: 'complete'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember3 { + /** + * Information about the completed login + */ + export interface Complete { + /** + * The unique ID of a login. Defined by the network connector. + */ + user_login_id?: string; + } + } +} + +/** + * A step in a login process. + */ +export type AuthSubmitUserInputResponse = + | AuthSubmitUserInputResponse.UnionMember0 + | AuthSubmitUserInputResponse.UnionMember1 + | AuthSubmitUserInputResponse.UnionMember2 + | AuthSubmitUserInputResponse.UnionMember3; + +export namespace AuthSubmitUserInputResponse { + /** + * Display and wait login step + */ + export interface UnionMember0 { + /** + * Parameters for the display and wait login step + */ + display_and_wait: UnionMember0.DisplayAndWait; + + type: 'display_and_wait'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember0 { + /** + * Parameters for the display and wait login step + */ + export interface DisplayAndWait { + /** + * The type of thing to display + */ + type: 'qr' | 'emoji' | 'code' | 'nothing'; + + /** + * The thing to display (raw data for QR, unicode emoji for emoji, plain string for + * code) + */ + data?: string; + + /** + * An image containing the thing to display. If present, this is recommended over + * using data directly. For emojis, the URL to the canonical image representation + * of the emoji + */ + image_url?: string; + } + } + + /** + * User input login step + */ + export interface UnionMember1 { + type: 'user_input'; + + /** + * Parameters for the user input login step + */ + user_input: UnionMember1.UserInput; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember1 { + /** + * Parameters for the user input login step + */ + export interface UserInput { + /** + * The list of fields that the user is requested to fill. + */ + fields: Array; + + /** + * A list of media attachments to show the user alongside the form fields. + */ + attachments?: Array; + } + + export namespace UserInput { + /** + * A field that the user can fill. + */ + export interface Field { + /** + * The internal ID of the field. This must be used as the key in the object when + * submitting the data back to the bridge. + */ + id: string; + + /** + * The name of the field shown to the user. + */ + name: string; + + /** + * The type of field. + */ + type: + | 'username' + | 'phone_number' + | 'email' + | 'password' + | '2fa_code' + | 'token' + | 'url' + | 'domain' + | 'select'; + + /** + * A default value that the client can pre-fill the field with. + */ + default_value?: string; + + /** + * A more detailed description of the field shown to the user. + */ + description?: string; + + /** + * For fields of type select, the valid options. + */ + options?: Array; + + /** + * A regular expression that the field value must match. + */ + pattern?: string; + } + + /** + * A media attachment to show the user. + */ + export interface Attachment { + /** + * The raw file content for the attachment encoded in base64. + */ + content: string; + + /** + * The filename for the media attachment. + */ + filename: string; + + /** + * The type of media attachment, using the same media type identifiers as Matrix + * attachments. Only some are supported. + */ + type: 'm.image' | 'm.audio'; + + /** + * Optional but recommended metadata for the attachment. Can generally be derived + * from the raw content if omitted. + */ + info?: Attachment.Info; + } + + export namespace Attachment { + /** + * Optional but recommended metadata for the attachment. Can generally be derived + * from the raw content if omitted. + */ + export interface Info { + /** + * The height of the media in pixels. Only applicable for images and videos. + */ + h?: number; + + /** + * The MIME type for the media content. + */ + mimetype?: string; + + /** + * The size of the media content in number of bytes. Strongly recommended to + * include. + */ + size?: number; + + /** + * The width of the media in pixels. Only applicable for images and videos. + */ + w?: number; + } + } + } + } + + /** + * Cookie login step + */ + export interface UnionMember2 { + /** + * Parameters for the cookie login step + */ + cookies: UnionMember2.Cookies; + + type: 'cookies'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember2 { + /** + * Parameters for the cookie login step + */ + export interface Cookies { + /** + * The list of cookies or other stored data that must be extracted. + */ + fields: Array; + + /** + * The URL to open when using a webview to extract cookies. + */ + url: string; + + /** + * A JavaScript snippet that can extract some or all of the fields. The snippet + * will evaluate to a promise that resolves when the relevant fields are found. + * Fields that are not present in the promise result must be extracted another way. + */ + extract_js?: string; + + /** + * An optional user agent that the webview should use. + */ + user_agent?: string; + + /** + * A regex pattern that the URL should match before the client closes the webview. + * + * The client may submit the login if the user closes the webview after all cookies + * are collected even if this URL is not reached, but it should only automatically + * close the webview after both cookies and the URL match. + */ + wait_for_url_pattern?: string; + } + + export namespace Cookies { + /** + * An individual cookie or other stored data item that must be extracted. + */ + export interface Field { + /** + * The name of the item to extract. + */ + name: string; + + /** + * The type of data to extract. + */ + type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; + + /** + * For the `cookie` type, the domain of the cookie. + */ + cookie_domain?: string; + + /** + * For the `request_header` and `request_body` types, a regex that matches the URLs + * from which the values can be extracted. + */ + request_url_regex?: string; + } + } + } + + /** + * Login complete + */ + export interface UnionMember3 { + /** + * Information about the completed login + */ + complete: UnionMember3.Complete; + + type: 'complete'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember3 { + /** + * Information about the completed login + */ + export interface Complete { + /** + * The unique ID of a login. Defined by the network connector. + */ + user_login_id?: string; + } + } +} + +/** + * A step in a login process. + */ +export type AuthWaitForStepResponse = + | AuthWaitForStepResponse.UnionMember0 + | AuthWaitForStepResponse.UnionMember1 + | AuthWaitForStepResponse.UnionMember2 + | AuthWaitForStepResponse.UnionMember3; + +export namespace AuthWaitForStepResponse { + /** + * Display and wait login step + */ + export interface UnionMember0 { + /** + * Parameters for the display and wait login step + */ + display_and_wait: UnionMember0.DisplayAndWait; + + type: 'display_and_wait'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember0 { + /** + * Parameters for the display and wait login step + */ + export interface DisplayAndWait { + /** + * The type of thing to display + */ + type: 'qr' | 'emoji' | 'code' | 'nothing'; + + /** + * The thing to display (raw data for QR, unicode emoji for emoji, plain string for + * code) + */ + data?: string; + + /** + * An image containing the thing to display. If present, this is recommended over + * using data directly. For emojis, the URL to the canonical image representation + * of the emoji + */ + image_url?: string; + } + } + + /** + * User input login step + */ + export interface UnionMember1 { + type: 'user_input'; + + /** + * Parameters for the user input login step + */ + user_input: UnionMember1.UserInput; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember1 { + /** + * Parameters for the user input login step + */ + export interface UserInput { + /** + * The list of fields that the user is requested to fill. + */ + fields: Array; + + /** + * A list of media attachments to show the user alongside the form fields. + */ + attachments?: Array; + } + + export namespace UserInput { + /** + * A field that the user can fill. + */ + export interface Field { + /** + * The internal ID of the field. This must be used as the key in the object when + * submitting the data back to the bridge. + */ + id: string; + + /** + * The name of the field shown to the user. + */ + name: string; + + /** + * The type of field. + */ + type: + | 'username' + | 'phone_number' + | 'email' + | 'password' + | '2fa_code' + | 'token' + | 'url' + | 'domain' + | 'select'; + + /** + * A default value that the client can pre-fill the field with. + */ + default_value?: string; + + /** + * A more detailed description of the field shown to the user. + */ + description?: string; + + /** + * For fields of type select, the valid options. + */ + options?: Array; + + /** + * A regular expression that the field value must match. + */ + pattern?: string; + } + + /** + * A media attachment to show the user. + */ + export interface Attachment { + /** + * The raw file content for the attachment encoded in base64. + */ + content: string; + + /** + * The filename for the media attachment. + */ + filename: string; + + /** + * The type of media attachment, using the same media type identifiers as Matrix + * attachments. Only some are supported. + */ + type: 'm.image' | 'm.audio'; + + /** + * Optional but recommended metadata for the attachment. Can generally be derived + * from the raw content if omitted. + */ + info?: Attachment.Info; + } + + export namespace Attachment { + /** + * Optional but recommended metadata for the attachment. Can generally be derived + * from the raw content if omitted. + */ + export interface Info { + /** + * The height of the media in pixels. Only applicable for images and videos. + */ + h?: number; + + /** + * The MIME type for the media content. + */ + mimetype?: string; + + /** + * The size of the media content in number of bytes. Strongly recommended to + * include. + */ + size?: number; + + /** + * The width of the media in pixels. Only applicable for images and videos. + */ + w?: number; + } + } + } + } + + /** + * Cookie login step + */ + export interface UnionMember2 { + /** + * Parameters for the cookie login step + */ + cookies: UnionMember2.Cookies; + + type: 'cookies'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember2 { + /** + * Parameters for the cookie login step + */ + export interface Cookies { + /** + * The list of cookies or other stored data that must be extracted. + */ + fields: Array; + + /** + * The URL to open when using a webview to extract cookies. + */ + url: string; + + /** + * A JavaScript snippet that can extract some or all of the fields. The snippet + * will evaluate to a promise that resolves when the relevant fields are found. + * Fields that are not present in the promise result must be extracted another way. + */ + extract_js?: string; + + /** + * An optional user agent that the webview should use. + */ + user_agent?: string; + + /** + * A regex pattern that the URL should match before the client closes the webview. + * + * The client may submit the login if the user closes the webview after all cookies + * are collected even if this URL is not reached, but it should only automatically + * close the webview after both cookies and the URL match. + */ + wait_for_url_pattern?: string; + } + + export namespace Cookies { + /** + * An individual cookie or other stored data item that must be extracted. + */ + export interface Field { + /** + * The name of the item to extract. + */ + name: string; + + /** + * The type of data to extract. + */ + type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; + + /** + * For the `cookie` type, the domain of the cookie. + */ + cookie_domain?: string; + + /** + * For the `request_header` and `request_body` types, a regex that matches the URLs + * from which the values can be extracted. + */ + request_url_regex?: string; + } + } + } + + /** + * Login complete + */ + export interface UnionMember3 { + /** + * Information about the completed login + */ + complete: UnionMember3.Complete; + + type: 'complete'; + + /** + * Human-readable instructions for completing this login step. + */ + instructions?: string; + + /** + * An identifier for the current login process. Must be passed to execute more + * steps of the login. + */ + login_id?: string; + + /** + * An unique ID identifying this step. This can be used to implement special + * behavior in clients. + */ + step_id?: string; + } + + export namespace UnionMember3 { + /** + * Information about the completed login + */ + export interface Complete { + /** + * The unique ID of a login. Defined by the network connector. + */ + user_login_id?: string; + } + } +} + +/** + * Info about the bridge and user + */ +export interface AuthWhoamiResponse { + /** + * The Matrix user ID of the bridge bot. + */ + bridge_bot: string; + + /** + * The command prefix used by this bridge. + */ + command_prefix: string; + + /** + * The server name the bridge is running on. + */ + homeserver: string; + + /** + * The login flows that the bridge supports. + */ + login_flows: Array; + + /** + * The logins of the user who made the /whoami call + */ + logins: Array; + + /** + * Info about the network that the bridge is bridging to. + */ + network: AuthWhoamiResponse.Network; + + /** + * The Matrix management room ID of the user who made the /whoami call. + */ + management_room?: string; +} + +export namespace AuthWhoamiResponse { + /** + * An individual login flow which can be used to sign into the remote network. + */ + export interface LoginFlow { + /** + * An internal ID that is passed to the /login/start call to start a login with + * this flow. + */ + id: string; + + /** + * A human-readable description of the login flow. + */ + description: string; + + /** + * A human-readable name for the login flow. + */ + name: string; + } + + /** + * The info of an individual login + */ + export interface Login { + /** + * The unique ID of a login. Defined by the network connector. + */ + id: string; + + /** + * A human-readable name for the login. Defined by the network connector. + */ + name: string; + + /** + * The profile info of the logged-in user on the remote network. + */ + profile: Login.Profile; + + /** + * The connection status of an individual login + */ + state: Login.State; + + /** + * The personal filtering space room ID for this login. + */ + space_room?: string; + } + + export namespace Login { + /** + * The profile info of the logged-in user on the remote network. + */ + export interface Profile { + /** + * The user's avatar + */ + avatar?: string; + + /** + * The user's email address + */ + email?: string; + + /** + * The user's displayname + */ + name?: string; + + /** + * The user's phone number + */ + phone?: string; + + /** + * The user's username + */ + username?: string; + } + + /** + * The connection status of an individual login + */ + export interface State { + /** + * The current state of this login. + */ + state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; + + /** + * The time when the state was last updated. + */ + timestamp: number; + + /** + * An error code defined by the network connector. + */ + error?: string; + + /** + * Additional arbitrary info provided by the network connector. + */ + info?: unknown; + + /** + * A human-readable error message defined by the network connector. + */ + message?: string; + + /** + * A reason code for non-error states that aren't exactly successes either. + */ + reason?: string; + } + } + + /** + * Info about the network that the bridge is bridging to. + */ + export interface Network { + /** + * An identifier uniquely identifying the bridge software. + */ + beeper_bridge_type: string; + + /** + * The displayname of the network. + */ + displayname: string; + + /** + * The icon of the network as a `mxc://` URI. + */ + network_icon: string; + + /** + * An identifier uniquely identifying the network. + */ + network_id: string; + + /** + * The URL to the website of the network. + */ + network_url: string; + } +} + +export interface AuthLogoutParams { + /** + * Bridge ID for the connected network account, for example discordgo or + * local-whatsapp. + */ + bridgeID: string; +} + +export interface AuthStartLoginParams { + /** + * Path param: Bridge ID for the connected network account, for example discordgo + * or local-whatsapp. + */ + bridgeID: string; + + /** + * Query param: An existing login ID to re-login as. If this is specified and the + * user logs into a different account, the provided ID will be logged out. + */ + login_id?: string; +} + +export interface AuthSubmitCookiesParams { + /** + * Path param: Bridge ID for the connected network account, for example discordgo + * or local-whatsapp. + */ + bridgeID: string; + + /** + * Path param: The ID of the login process, as returned in the `login_id` field of + * the start call. + */ + loginProcessID: string; + + /** + * Body param + */ + body: { [key: string]: string }; +} + +export interface AuthSubmitUserInputParams { + /** + * Path param: Bridge ID for the connected network account, for example discordgo + * or local-whatsapp. + */ + bridgeID: string; + + /** + * Path param: The ID of the login process, as returned in the `login_id` field of + * the start call. + */ + loginProcessID: string; + + /** + * Body param + */ + body: { [key: string]: string }; +} + +export interface AuthWaitForStepParams { + /** + * Bridge ID for the connected network account, for example discordgo or + * local-whatsapp. + */ + bridgeID: string; + + /** + * The ID of the login process, as returned in the `login_id` field of the start + * call. + */ + loginProcessID: string; +} + +export declare namespace Auth { + export { + type AuthListFlowsResponse as AuthListFlowsResponse, + type AuthListLoginsResponse as AuthListLoginsResponse, + type AuthLogoutResponse as AuthLogoutResponse, + type AuthStartLoginResponse as AuthStartLoginResponse, + type AuthSubmitCookiesResponse as AuthSubmitCookiesResponse, + type AuthSubmitUserInputResponse as AuthSubmitUserInputResponse, + type AuthWaitForStepResponse as AuthWaitForStepResponse, + type AuthWhoamiResponse as AuthWhoamiResponse, + type AuthLogoutParams as AuthLogoutParams, + type AuthStartLoginParams as AuthStartLoginParams, + type AuthSubmitCookiesParams as AuthSubmitCookiesParams, + type AuthSubmitUserInputParams as AuthSubmitUserInputParams, + type AuthWaitForStepParams as AuthWaitForStepParams, + }; +} diff --git a/src/resources/matrix/bridges/bridges.ts b/src/resources/matrix/bridges/bridges.ts new file mode 100644 index 00000000..5e70826d --- /dev/null +++ b/src/resources/matrix/bridges/bridges.ts @@ -0,0 +1,125 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as AuthAPI from './auth'; +import { + Auth, + AuthListFlowsResponse, + AuthListLoginsResponse, + AuthLogoutParams, + AuthLogoutResponse, + AuthStartLoginParams, + AuthStartLoginResponse, + AuthSubmitCookiesParams, + AuthSubmitCookiesResponse, + AuthSubmitUserInputParams, + AuthSubmitUserInputResponse, + AuthWaitForStepParams, + AuthWaitForStepResponse, + AuthWhoamiResponse, + BaseAuth, +} from './auth'; +import * as CapabilitiesAPI from './capabilities'; +import { BaseCapabilities, Capabilities, CapabilityRetrieveResponse } from './capabilities'; +import * as ContactsAPI from './contacts'; +import { BaseContacts, ContactListParams, ContactListResponse, Contacts } from './contacts'; +import * as RoomsAPI from './rooms'; +import { + BaseRooms, + RoomCreateDmParams, + RoomCreateDmResponse, + RoomCreateGroupParams, + RoomCreateGroupResponse, + Rooms, +} from './rooms'; +import * as UsersAPI from './users'; +import { + BaseUsers, + UserResolveParams, + UserResolveResponse, + UserSearchParams, + UserSearchResponse, + Users, +} from './users'; + +/** + * Matrix-compatible APIs for connected network bridges. + */ +export class BaseBridges extends APIResource { + static override readonly _key: readonly ['matrix', 'bridges'] = Object.freeze([ + 'matrix', + 'bridges', + ] as const); +} +/** + * Matrix-compatible APIs for connected network bridges. + */ +export class Bridges extends BaseBridges { + auth: AuthAPI.Auth = new AuthAPI.Auth(this._client); + contacts: ContactsAPI.Contacts = new ContactsAPI.Contacts(this._client); + users: UsersAPI.Users = new UsersAPI.Users(this._client); + rooms: RoomsAPI.Rooms = new RoomsAPI.Rooms(this._client); + capabilities: CapabilitiesAPI.Capabilities = new CapabilitiesAPI.Capabilities(this._client); +} + +Bridges.Auth = Auth; +Bridges.BaseAuth = BaseAuth; +Bridges.Contacts = Contacts; +Bridges.BaseContacts = BaseContacts; +Bridges.Users = Users; +Bridges.BaseUsers = BaseUsers; +Bridges.Rooms = Rooms; +Bridges.BaseRooms = BaseRooms; +Bridges.Capabilities = Capabilities; +Bridges.BaseCapabilities = BaseCapabilities; + +export declare namespace Bridges { + export { + Auth as Auth, + BaseAuth as BaseAuth, + type AuthListFlowsResponse as AuthListFlowsResponse, + type AuthListLoginsResponse as AuthListLoginsResponse, + type AuthLogoutResponse as AuthLogoutResponse, + type AuthStartLoginResponse as AuthStartLoginResponse, + type AuthSubmitCookiesResponse as AuthSubmitCookiesResponse, + type AuthSubmitUserInputResponse as AuthSubmitUserInputResponse, + type AuthWaitForStepResponse as AuthWaitForStepResponse, + type AuthWhoamiResponse as AuthWhoamiResponse, + type AuthLogoutParams as AuthLogoutParams, + type AuthStartLoginParams as AuthStartLoginParams, + type AuthSubmitCookiesParams as AuthSubmitCookiesParams, + type AuthSubmitUserInputParams as AuthSubmitUserInputParams, + type AuthWaitForStepParams as AuthWaitForStepParams, + }; + + export { + Contacts as Contacts, + BaseContacts as BaseContacts, + type ContactListResponse as ContactListResponse, + type ContactListParams as ContactListParams, + }; + + export { + Users as Users, + BaseUsers as BaseUsers, + type UserResolveResponse as UserResolveResponse, + type UserSearchResponse as UserSearchResponse, + type UserResolveParams as UserResolveParams, + type UserSearchParams as UserSearchParams, + }; + + export { + Rooms as Rooms, + BaseRooms as BaseRooms, + type RoomCreateDmResponse as RoomCreateDmResponse, + type RoomCreateGroupResponse as RoomCreateGroupResponse, + type RoomCreateDmParams as RoomCreateDmParams, + type RoomCreateGroupParams as RoomCreateGroupParams, + }; + + export { + Capabilities as Capabilities, + BaseCapabilities as BaseCapabilities, + type CapabilityRetrieveResponse as CapabilityRetrieveResponse, + }; +} diff --git a/src/resources/matrix/bridges/capabilities.ts b/src/resources/matrix/bridges/capabilities.ts new file mode 100644 index 00000000..40ac3b0a --- /dev/null +++ b/src/resources/matrix/bridges/capabilities.ts @@ -0,0 +1,45 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class BaseCapabilities extends APIResource { + static override readonly _key: readonly ['matrix', 'bridges', 'capabilities'] = Object.freeze([ + 'matrix', + 'bridges', + 'capabilities', + ] as const); + + /** + * Get bridge capabilities + * + * @example + * ```ts + * const capability = + * await client.matrix.bridges.capabilities.retrieve( + * 'bridgeID', + * ); + * ``` + */ + retrieve(bridgeID: string, options?: RequestOptions): APIPromise { + return this._client.get( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/capabilities`, + options, + ); + } +} +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class Capabilities extends BaseCapabilities {} + +export type CapabilityRetrieveResponse = { [key: string]: unknown }; + +export declare namespace Capabilities { + export { type CapabilityRetrieveResponse as CapabilityRetrieveResponse }; +} diff --git a/src/resources/matrix/bridges/contacts.ts b/src/resources/matrix/bridges/contacts.ts new file mode 100644 index 00000000..8df20884 --- /dev/null +++ b/src/resources/matrix/bridges/contacts.ts @@ -0,0 +1,94 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class BaseContacts extends APIResource { + static override readonly _key: readonly ['matrix', 'bridges', 'contacts'] = Object.freeze([ + 'matrix', + 'bridges', + 'contacts', + ] as const); + + /** + * Get a list of contacts. + * + * @example + * ```ts + * const contacts = await client.matrix.bridges.contacts.list( + * 'bridgeID', + * ); + * ``` + */ + list( + bridgeID: string, + query: ContactListParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.get( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/contacts`, + { query, ...options }, + ); + } +} +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class Contacts extends BaseContacts {} + +export interface ContactListResponse { + contacts?: Array; +} + +export namespace ContactListResponse { + /** + * A successfully resolved identifier. + */ + export interface Contact { + /** + * The internal user ID of the resolved user. + */ + id: string; + + /** + * The avatar of the user on the remote network. + */ + avatar_url?: string; + + /** + * The Matrix room ID of the direct chat with the user. + */ + dm_room_mxid?: string; + + /** + * A list of identifiers for the user on the remote network. + */ + identifiers?: Array; + + /** + * The Matrix user ID of the ghost representing the user. + */ + mxid?: string; + + /** + * The name of the user on the remote network. + */ + name?: string; + } +} + +export interface ContactListParams { + /** + * An optional explicit login ID to do the action through. + */ + login_id?: string; +} + +export declare namespace Contacts { + export { type ContactListResponse as ContactListResponse, type ContactListParams as ContactListParams }; +} diff --git a/src/resources/matrix/bridges/index.ts b/src/resources/matrix/bridges/index.ts new file mode 100644 index 00000000..f0230f7c --- /dev/null +++ b/src/resources/matrix/bridges/index.ts @@ -0,0 +1,38 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Auth, + BaseAuth, + type AuthListFlowsResponse, + type AuthListLoginsResponse, + type AuthLogoutResponse, + type AuthStartLoginResponse, + type AuthSubmitCookiesResponse, + type AuthSubmitUserInputResponse, + type AuthWaitForStepResponse, + type AuthWhoamiResponse, + type AuthLogoutParams, + type AuthStartLoginParams, + type AuthSubmitCookiesParams, + type AuthSubmitUserInputParams, + type AuthWaitForStepParams, +} from './auth'; +export { Bridges, BaseBridges } from './bridges'; +export { Capabilities, BaseCapabilities, type CapabilityRetrieveResponse } from './capabilities'; +export { Contacts, BaseContacts, type ContactListResponse, type ContactListParams } from './contacts'; +export { + Rooms, + BaseRooms, + type RoomCreateDmResponse, + type RoomCreateGroupResponse, + type RoomCreateDmParams, + type RoomCreateGroupParams, +} from './rooms'; +export { + Users, + BaseUsers, + type UserResolveResponse, + type UserSearchResponse, + type UserResolveParams, + type UserSearchParams, +} from './users'; diff --git a/src/resources/matrix/bridges/rooms.ts b/src/resources/matrix/bridges/rooms.ts new file mode 100644 index 00000000..d5275fa0 --- /dev/null +++ b/src/resources/matrix/bridges/rooms.ts @@ -0,0 +1,231 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class BaseRooms extends APIResource { + static override readonly _key: readonly ['matrix', 'bridges', 'rooms'] = Object.freeze([ + 'matrix', + 'bridges', + 'rooms', + ] as const); + + /** + * Create a direct chat with a user on the remote network. + * + * @example + * ```ts + * const response = await client.matrix.bridges.rooms.createDm( + * 'identifier', + * { bridgeID: 'bridgeID' }, + * ); + * ``` + */ + createDm( + identifier: string, + params: RoomCreateDmParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, login_id } = params; + return this._client.post( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/create_dm/${identifier}`, + { query: { login_id }, ...options }, + ); + } + + /** + * Create a group chat on the remote network. + * + * @example + * ```ts + * const response = + * await client.matrix.bridges.rooms.createGroup( + * 'groupType', + * { bridgeID: 'bridgeID' }, + * ); + * ``` + */ + createGroup( + groupType: string, + params: RoomCreateGroupParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, login_id, ...body } = params; + return this._client.post( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/create_group/${groupType}`, + { query: { login_id }, body, ...options }, + ); + } +} +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class Rooms extends BaseRooms {} + +/** + * A successfully resolved identifier. + */ +export interface RoomCreateDmResponse { + /** + * The internal user ID of the resolved user. + */ + id: string; + + /** + * The avatar of the user on the remote network. + */ + avatar_url?: string; + + /** + * The Matrix room ID of the direct chat with the user. + */ + dm_room_mxid?: string; + + /** + * A list of identifiers for the user on the remote network. + */ + identifiers?: Array; + + /** + * The Matrix user ID of the ghost representing the user. + */ + mxid?: string; + + /** + * The name of the user on the remote network. + */ + name?: string; +} + +/** + * A successfully created group chat. + */ +export interface RoomCreateGroupResponse { + /** + * The internal chat ID of the created group. + */ + id: string; + + /** + * The Matrix room ID of the portal. + */ + mxid: string; +} + +export interface RoomCreateDmParams { + /** + * Path param: Bridge ID for the connected network account, for example discordgo + * or local-whatsapp. + */ + bridgeID: string; + + /** + * Query param: An optional explicit login ID to do the action through. + */ + login_id?: string; +} + +export interface RoomCreateGroupParams { + /** + * Path param: Bridge ID for the connected network account, for example discordgo + * or local-whatsapp. + */ + bridgeID: string; + + /** + * Query param: An optional explicit login ID to do the action through. + */ + login_id?: string; + + /** + * Body param: The `m.room.avatar` event content for the room. + */ + avatar?: RoomCreateGroupParams.Avatar; + + /** + * Body param: The `com.beeper.disappearing_timer` event content for the room. + */ + disappear?: RoomCreateGroupParams.Disappear; + + /** + * Body param: The `m.room.name` event content for the room. + */ + name?: RoomCreateGroupParams.Name; + + /** + * Body param + */ + parent?: unknown; + + /** + * Body param: The users to add to the group initially. + */ + participants?: Array; + + /** + * Body param: An existing Matrix room ID to bridge to. The other parameters must + * be already in sync with the room state when using this parameter. + */ + room_id?: string; + + /** + * Body param: The `m.room.topic` event content for the room. + */ + topic?: RoomCreateGroupParams.Topic; + + /** + * Body param: The type of group to create. + */ + type?: string; + + /** + * Body param: The public username for the created group. + */ + username?: string; +} + +export namespace RoomCreateGroupParams { + /** + * The `m.room.avatar` event content for the room. + */ + export interface Avatar { + url?: string; + } + + /** + * The `com.beeper.disappearing_timer` event content for the room. + */ + export interface Disappear { + timer?: number; + + type?: string; + } + + /** + * The `m.room.name` event content for the room. + */ + export interface Name { + name?: string; + } + + /** + * The `m.room.topic` event content for the room. + */ + export interface Topic { + topic?: string; + } +} + +export declare namespace Rooms { + export { + type RoomCreateDmResponse as RoomCreateDmResponse, + type RoomCreateGroupResponse as RoomCreateGroupResponse, + type RoomCreateDmParams as RoomCreateDmParams, + type RoomCreateGroupParams as RoomCreateGroupParams, + }; +} diff --git a/src/resources/matrix/bridges/users.ts b/src/resources/matrix/bridges/users.ts new file mode 100644 index 00000000..473c9235 --- /dev/null +++ b/src/resources/matrix/bridges/users.ts @@ -0,0 +1,176 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class BaseUsers extends APIResource { + static override readonly _key: readonly ['matrix', 'bridges', 'users'] = Object.freeze([ + 'matrix', + 'bridges', + 'users', + ] as const); + + /** + * Resolve an identifier to a user on the remote network. + * + * @example + * ```ts + * const response = await client.matrix.bridges.users.resolve( + * 'identifier', + * { bridgeID: 'bridgeID' }, + * ); + * ``` + */ + resolve( + identifier: string, + params: UserResolveParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, ...query } = params; + return this._client.get( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/resolve_identifier/${identifier}`, + { query, ...options }, + ); + } + + /** + * Search for users on the remote network + * + * @example + * ```ts + * const response = await client.matrix.bridges.users.search( + * 'bridgeID', + * ); + * ``` + */ + search( + bridgeID: string, + params: UserSearchParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + const { login_id, ...body } = params ?? {}; + return this._client.post( + path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/search_users`, + { query: { login_id }, body, ...options }, + ); + } +} +/** + * Matrix-compatible APIs for accounts and connected network bridges. + */ +export class Users extends BaseUsers {} + +/** + * A successfully resolved identifier. + */ +export interface UserResolveResponse { + /** + * The internal user ID of the resolved user. + */ + id: string; + + /** + * The avatar of the user on the remote network. + */ + avatar_url?: string; + + /** + * The Matrix room ID of the direct chat with the user. + */ + dm_room_mxid?: string; + + /** + * A list of identifiers for the user on the remote network. + */ + identifiers?: Array; + + /** + * The Matrix user ID of the ghost representing the user. + */ + mxid?: string; + + /** + * The name of the user on the remote network. + */ + name?: string; +} + +export interface UserSearchResponse { + results?: Array; +} + +export namespace UserSearchResponse { + /** + * A successfully resolved identifier. + */ + export interface Result { + /** + * The internal user ID of the resolved user. + */ + id: string; + + /** + * The avatar of the user on the remote network. + */ + avatar_url?: string; + + /** + * The Matrix room ID of the direct chat with the user. + */ + dm_room_mxid?: string; + + /** + * A list of identifiers for the user on the remote network. + */ + identifiers?: Array; + + /** + * The Matrix user ID of the ghost representing the user. + */ + mxid?: string; + + /** + * The name of the user on the remote network. + */ + name?: string; + } +} + +export interface UserResolveParams { + /** + * Path param: Bridge ID for the connected network account, for example discordgo + * or local-whatsapp. + */ + bridgeID: string; + + /** + * Query param: An optional explicit login ID to do the action through. + */ + login_id?: string; +} + +export interface UserSearchParams { + /** + * Query param: An optional explicit login ID to do the action through. + */ + login_id?: string; + + /** + * Body param: The search query to send to the remote network + */ + query?: string; +} + +export declare namespace Users { + export { + type UserResolveResponse as UserResolveResponse, + type UserSearchResponse as UserSearchResponse, + type UserResolveParams as UserResolveParams, + type UserSearchParams as UserSearchParams, + }; +} diff --git a/src/resources/matrix/index.ts b/src/resources/matrix/index.ts new file mode 100644 index 00000000..3da24c40 --- /dev/null +++ b/src/resources/matrix/index.ts @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { Bridges, BaseBridges } from './bridges/index'; +export { Matrix, BaseMatrix } from './matrix'; +export { + Rooms, + BaseRooms, + type RoomCreateResponse, + type RoomJoinResponse, + type RoomLeaveResponse, + type RoomCreateParams, + type RoomJoinParams, + type RoomLeaveParams, +} from './rooms/index'; +export { Users, BaseUsers, type UserRetrieveProfileResponse } from './users/index'; diff --git a/src/resources/matrix/matrix.ts b/src/resources/matrix/matrix.ts new file mode 100644 index 00000000..33b6e940 --- /dev/null +++ b/src/resources/matrix/matrix.ts @@ -0,0 +1,61 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as BridgesAPI from './bridges/bridges'; +import { BaseBridges, Bridges } from './bridges/bridges'; +import * as RoomsAPI from './rooms/rooms'; +import { + BaseRooms, + RoomCreateParams, + RoomCreateResponse, + RoomJoinParams, + RoomJoinResponse, + RoomLeaveParams, + RoomLeaveResponse, + Rooms, +} from './rooms/rooms'; +import * as UsersAPI from './users/users'; +import { BaseUsers, UserRetrieveProfileResponse, Users } from './users/users'; + +/** + * Matrix-compatible APIs for accounts, rooms, and connected network bridges. + */ +export class BaseMatrix extends APIResource { + static override readonly _key: readonly ['matrix'] = Object.freeze(['matrix'] as const); +} +/** + * Matrix-compatible APIs for accounts, rooms, and connected network bridges. + */ +export class Matrix extends BaseMatrix { + users: UsersAPI.Users = new UsersAPI.Users(this._client); + rooms: RoomsAPI.Rooms = new RoomsAPI.Rooms(this._client); + bridges: BridgesAPI.Bridges = new BridgesAPI.Bridges(this._client); +} + +Matrix.Users = Users; +Matrix.BaseUsers = BaseUsers; +Matrix.Rooms = Rooms; +Matrix.BaseRooms = BaseRooms; +Matrix.Bridges = Bridges; +Matrix.BaseBridges = BaseBridges; + +export declare namespace Matrix { + export { + Users as Users, + BaseUsers as BaseUsers, + type UserRetrieveProfileResponse as UserRetrieveProfileResponse, + }; + + export { + Rooms as Rooms, + BaseRooms as BaseRooms, + type RoomCreateResponse as RoomCreateResponse, + type RoomJoinResponse as RoomJoinResponse, + type RoomLeaveResponse as RoomLeaveResponse, + type RoomCreateParams as RoomCreateParams, + type RoomJoinParams as RoomJoinParams, + type RoomLeaveParams as RoomLeaveParams, + }; + + export { Bridges as Bridges, BaseBridges as BaseBridges }; +} diff --git a/src/resources/matrix/rooms.ts b/src/resources/matrix/rooms.ts new file mode 100644 index 00000000..22113d24 --- /dev/null +++ b/src/resources/matrix/rooms.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './rooms/index'; diff --git a/src/resources/matrix/rooms/account-data.ts b/src/resources/matrix/rooms/account-data.ts new file mode 100644 index 00000000..e2fcd393 --- /dev/null +++ b/src/resources/matrix/rooms/account-data.ts @@ -0,0 +1,113 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class BaseAccountData extends APIResource { + static override readonly _key: readonly ['matrix', 'rooms', 'accountData'] = Object.freeze([ + 'matrix', + 'rooms', + 'accountData', + ] as const); + + /** + * Get some account data for the client on a given room. This config is only + * visible to the user that set the account data. + * + * @example + * ```ts + * const accountData = + * await client.matrix.rooms.accountData.retrieve( + * 'org.example.custom.room.config', + * { + * userId: '@alice:example.com', + * roomId: '!726s6s6q:example.com', + * }, + * ); + * ``` + */ + retrieve(type: string, params: AccountDataRetrieveParams, options?: RequestOptions): APIPromise { + const { userId, roomId } = params; + return this._client.get( + path`/_matrix/client/v3/user/${userId}/rooms/${roomId}/account_data/${type}`, + options, + ); + } + + /** + * Set some account data for the client on a given room. This config is only + * visible to the user that set the account data. The config will be delivered to + * clients in the per-room entries via + * [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync). + * + * @example + * ```ts + * const accountData = + * await client.matrix.rooms.accountData.update( + * 'org.example.custom.room.config', + * { + * userId: '@alice:example.com', + * roomId: '!726s6s6q:example.com', + * body: { + * custom_account_data_key: + * 'custom_account_data_value', + * }, + * }, + * ); + * ``` + */ + update(type: string, params: AccountDataUpdateParams, options?: RequestOptions): APIPromise { + const { userId, roomId, body } = params; + return this._client.put(path`/_matrix/client/v3/user/${userId}/rooms/${roomId}/account_data/${type}`, { + body: body, + ...options, + }); + } +} +export class AccountData extends BaseAccountData {} + +export type AccountDataRetrieveResponse = unknown; + +export type AccountDataUpdateResponse = unknown; + +export interface AccountDataRetrieveParams { + /** + * The ID of the user to get account data for. The access token must be authorized + * to make requests for this user ID. + */ + userId: string; + + /** + * The ID of the room to get account data for. + */ + roomId: string; +} + +export interface AccountDataUpdateParams { + /** + * Path param: The ID of the user to set account data for. The access token must be + * authorized to make requests for this user ID. + */ + userId: string; + + /** + * Path param: The ID of the room to set account data on. + */ + roomId: string; + + /** + * Body param + */ + body: unknown; +} + +export declare namespace AccountData { + export { + type AccountDataRetrieveResponse as AccountDataRetrieveResponse, + type AccountDataUpdateResponse as AccountDataUpdateResponse, + type AccountDataRetrieveParams as AccountDataRetrieveParams, + type AccountDataUpdateParams as AccountDataUpdateParams, + }; +} diff --git a/src/resources/matrix/rooms/events.ts b/src/resources/matrix/rooms/events.ts new file mode 100644 index 00000000..b8fe4e22 --- /dev/null +++ b/src/resources/matrix/rooms/events.ts @@ -0,0 +1,148 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class BaseEvents extends APIResource { + static override readonly _key: readonly ['matrix', 'rooms', 'events'] = Object.freeze([ + 'matrix', + 'rooms', + 'events', + ] as const); + + /** + * Get a single event based on `roomId/eventId`. You must have permission to + * retrieve this event e.g. by being a member in the room for this event. + * + * @example + * ```ts + * const event = await client.matrix.rooms.events.retrieve( + * '$asfDuShaf7Gafaw:matrix.org', + * { roomId: '!636q39766251:matrix.org' }, + * ); + * ``` + */ + retrieve( + eventID: string, + params: EventRetrieveParams, + options?: RequestOptions, + ): APIPromise { + const { roomId } = params; + return this._client.get(path`/_matrix/client/v3/rooms/${roomId}/event/${eventID}`, options); + } +} +export class Events extends BaseEvents {} + +/** + * The format used for events when they are returned from a homeserver to a client + * via the Client-Server API, or sent to an Application Service via the Application + * Services API. + */ +export interface EventRetrieveResponse { + /** + * The body of this event, as created by the client which sent it. + */ + content: unknown; + + /** + * The globally unique identifier for this event. + */ + event_id: string; + + /** + * Timestamp (in milliseconds since the unix epoch) on originating homeserver when + * this event was sent. + */ + origin_server_ts: number; + + /** + * The ID of the room associated with this event. + */ + room_id: string; + + /** + * Contains the fully-qualified ID of the user who sent this event. + */ + sender: string; + + /** + * The type of the event. + */ + type: string; + + /** + * Present if, and only if, this event is a _state_ event. The key making this + * piece of state unique in the room. Note that it is often an empty string. + * + * State keys starting with an `@` are reserved for referencing user IDs, such as + * room members. With the exception of a few events, state events set with a given + * user's ID as the state key MUST only be set by that user. + */ + state_key?: string; + + unsigned?: EventRetrieveResponse.Unsigned; +} + +export namespace EventRetrieveResponse { + export interface Unsigned { + /** + * The time in milliseconds that has elapsed since the event was sent. This field + * is generated by the local homeserver, and may be incorrect if the local time on + * at least one of the two servers is out of sync, which can cause the age to + * either be negative or greater than it actually is. + */ + age?: number; + + /** + * The room membership of the user making the request, at the time of the event. + * + * This property is the value of the `membership` property of the requesting user's + * [`m.room.member`](https://spec.matrix.org/v1.18/client-server-api#mroommember) + * state at the point of the event, including any changes caused by the event. If + * the user had yet to join the room at the time of the event (i.e, they have no + * `m.room.member` state), this property is set to `leave`. + * + * Homeservers SHOULD populate this property wherever practical, but they MAY omit + * it if necessary (for example, if calculating the value is expensive, servers + * might choose to only implement it in encrypted rooms). The property is _not_ + * normally populated in events pushed to application services via the application + * service transaction API (where there is no clear definition of "requesting + * user"). + */ + membership?: string; + + /** + * The previous `content` for this event. This field is generated by the local + * homeserver, and is only returned if the event is a state event, and the client + * has permission to see the previous content. + */ + prev_content?: unknown; + + redacted_because?: unknown; + + /** + * The client-supplied + * [transaction ID](https://spec.matrix.org/v1.18/client-server-api/#transaction-identifiers), + * for example, provided via + * `PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}`, if the client + * being given the event is the same one which sent it. + */ + transaction_id?: string; + } +} + +export interface EventRetrieveParams { + /** + * The ID of the room the event is in. + */ + roomId: string; +} + +export declare namespace Events { + export { + type EventRetrieveResponse as EventRetrieveResponse, + type EventRetrieveParams as EventRetrieveParams, + }; +} diff --git a/src/resources/matrix/rooms/index.ts b/src/resources/matrix/rooms/index.ts new file mode 100644 index 00000000..7c206b25 --- /dev/null +++ b/src/resources/matrix/rooms/index.ts @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + AccountData, + BaseAccountData, + type AccountDataRetrieveResponse, + type AccountDataUpdateResponse, + type AccountDataRetrieveParams, + type AccountDataUpdateParams, +} from './account-data'; +export { Events, BaseEvents, type EventRetrieveResponse, type EventRetrieveParams } from './events'; +export { + Rooms, + BaseRooms, + type RoomCreateResponse, + type RoomJoinResponse, + type RoomLeaveResponse, + type RoomCreateParams, + type RoomJoinParams, + type RoomLeaveParams, +} from './rooms'; +export { + State, + BaseState, + type StateRetrieveResponse, + type StateListResponse, + type StateRetrieveParams, +} from './state'; diff --git a/src/resources/matrix/rooms/rooms.ts b/src/resources/matrix/rooms/rooms.ts new file mode 100644 index 00000000..9c4456ca --- /dev/null +++ b/src/resources/matrix/rooms/rooms.ts @@ -0,0 +1,435 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as AccountDataAPI from './account-data'; +import { + AccountData, + AccountDataRetrieveParams, + AccountDataRetrieveResponse, + AccountDataUpdateParams, + AccountDataUpdateResponse, + BaseAccountData, +} from './account-data'; +import * as EventsAPI from './events'; +import { BaseEvents, EventRetrieveParams, EventRetrieveResponse, Events } from './events'; +import * as StateAPI from './state'; +import { BaseState, State, StateListResponse, StateRetrieveParams, StateRetrieveResponse } from './state'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class BaseRooms extends APIResource { + static override readonly _key: readonly ['matrix', 'rooms'] = Object.freeze(['matrix', 'rooms'] as const); + + /** + * Create a new room with various configuration options. + * + * The server MUST apply the normal state resolution rules when creating the new + * room, including checking power levels for each event. It MUST apply the events + * implied by the request in the following order: + * + * 1. The `m.room.create` event itself. Must be the first event in the room. + * + * 2. An `m.room.member` event for the creator to join the room. This is needed so + * the remaining events can be sent. + * + * 3. A default `m.room.power_levels` event. Overridden by the + * `power_level_content_override` parameter. + * + * In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the + * room creator (and not other members) will be given permission to send state + * events. + * + * In room versions 12 and later, the room creator is given infinite power level + * and cannot be specified in the `users` field of `m.room.power_levels`, so is + * not listed explicitly. + * + * **Note**: For `trusted_private_chat`, the users specified in the `invite` + * parameter SHOULD also be appended to `additional_creators` by the server, per + * the `creation_content` parameter. + * + * If the room's version is 12 or higher, the power level for sending + * `m.room.tombstone` events MUST explicitly be higher than `state_default`. For + * example, set to 150 instead of 100. + * + * 4. An `m.room.canonical_alias` event if `room_alias_name` is given. + * + * 5. Events set by the `preset`. Currently these are the `m.room.join_rules`, + * `m.room.history_visibility`, and `m.room.guest_access` state events. + * + * 6. Events listed in `initial_state`, in the order that they are listed. + * + * 7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` state + * events). + * + * 8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with + * `membership: invite` and `m.room.third_party_invite`). + * + * The available presets do the following with respect to room state: + * + * | Preset | `join_rules` | `history_visibility` | `guest_access` | Other | + * | ---------------------- | ------------ | -------------------- | -------------- | ---------------------------------------------------------------- | + * | `private_chat` | `invite` | `shared` | `can_join` | | + * | `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. | + * | `public_chat` | `public` | `shared` | `forbidden` | | + * + * The server will create a `m.room.create` event in the room with the requesting + * user as the creator, alongside other keys provided in the `creation_content` or + * implied by behaviour of `creation_content`. + * + * @example + * ```ts + * const room = await client.matrix.rooms.create(); + * ``` + */ + create(body: RoomCreateParams, options?: RequestOptions): APIPromise { + return this._client.post('/_matrix/client/v3/createRoom', { body, ...options }); + } + + /** + * _Note that this API takes either a room ID or alias, unlike_ + * `/rooms/{roomId}/join`. + * + * This API starts a user's participation in a particular room, if that user is + * allowed to participate in that room. After this call, the client is allowed to + * see all current state events in the room, and all subsequent events associated + * with the room until the user leaves the room. + * + * After a user has joined a room, the room will appear as an entry in the response + * of the + * [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync) + * and + * [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) + * APIs. + * + * @example + * ```ts + * const response = await client.matrix.rooms.join( + * '!monkeys:matrix.org', + * ); + * ``` + */ + join( + roomIDOrAlias: string, + params: RoomJoinParams, + options?: RequestOptions, + ): APIPromise { + const { via, ...body } = params; + return this._client.post(path`/_matrix/client/v3/join/${roomIDOrAlias}`, { + query: { via }, + body, + ...options, + }); + } + + /** + * This API stops a user participating in a particular room. + * + * If the user was already in the room, they will no longer be able to see new + * events in the room. If the room requires an invite to join, they will need to be + * re-invited before they can re-join. + * + * If the user was invited to the room, but had not joined, this call serves to + * reject the invite. + * + * Servers MAY additionally forget the room when this endpoint is called – just as + * if the user had also invoked + * [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget). + * Servers that do this, MUST inform clients about this behavior using the + * [`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability) + * capability. + * + * If the server doesn't automatically forget the room, the user will still be + * allowed to retrieve history from the room which they were previously allowed to + * see. + * + * @example + * ```ts + * const response = await client.matrix.rooms.leave( + * '!nkl290a:matrix.org', + * ); + * ``` + */ + leave(roomID: string, body: RoomLeaveParams, options?: RequestOptions): APIPromise { + return this._client.post(path`/_matrix/client/v3/rooms/${roomID}/leave`, { body, ...options }); + } +} +export class Rooms extends BaseRooms { + accountData: AccountDataAPI.AccountData = new AccountDataAPI.AccountData(this._client); + state: StateAPI.State = new StateAPI.State(this._client); + events: EventsAPI.Events = new EventsAPI.Events(this._client); +} + +/** + * Information about the newly created room. + */ +export interface RoomCreateResponse { + /** + * The created room's ID. + */ + room_id: string; +} + +export interface RoomJoinResponse { + /** + * The joined room ID. + */ + room_id: string; +} + +export type RoomLeaveResponse = unknown; + +export interface RoomCreateParams { + /** + * Extra keys, such as `m.federate`, to be added to the content of the + * [`m.room.create`](https://spec.matrix.org/v1.18/client-server-api/#mroomcreate) + * event. + * + * The server will overwrite the following keys: `creator`, `room_version`. Future + * versions of the specification may allow the server to overwrite other keys. + * + * When using the `trusted_private_chat` preset, the server SHOULD combine + * `additional_creators` specified here and the `invite` array into the eventual + * `m.room.create` event's `additional_creators`, deduplicating between the two + * parameters. + */ + creation_content?: unknown; + + /** + * A list of state events to set in the new room. This allows the user to override + * the default state events set in the new room. The expected format of the state + * events are an object with type, state_key and content keys set. + * + * Takes precedence over events set by `preset`, but gets overridden by `name` and + * `topic` keys. + */ + initial_state?: Array; + + /** + * A list of user IDs to invite to the room. This will tell the server to invite + * everyone in the list to the newly created room. + */ + invite?: Array; + + /** + * A list of objects representing third-party IDs to invite into the room. + */ + invite_3pid?: Array; + + /** + * This flag makes the server set the `is_direct` flag on the `m.room.member` + * events sent to the users in `invite` and `invite_3pid`. See + * [Direct Messaging](https://spec.matrix.org/v1.18/client-server-api/#direct-messaging) + * for more information. + */ + is_direct?: boolean; + + /** + * If this is included, an + * [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname) + * event will be sent into the room to indicate the name for the room. This + * overwrites any + * [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname) + * event in `initial_state`. + */ + name?: string; + + /** + * The power level content to override in the default power level event. This + * object is applied on top of the generated + * [`m.room.power_levels`](https://spec.matrix.org/v1.18/client-server-api/#mroompower_levels) + * event content prior to it being sent to the room. Defaults to overriding + * nothing. + */ + power_level_content_override?: unknown; + + /** + * Convenience parameter for setting various default state events based on a + * preset. + * + * If unspecified, the server should use the `visibility` to determine which preset + * to use. A visibility of `public` equates to a preset of `public_chat` and + * `private` visibility equates to a preset of `private_chat`. + */ + preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat'; + + /** + * The desired room alias **local part**. If this is included, a room alias will be + * created and mapped to the newly created room. The alias will belong on the + * _same_ homeserver which created the room. For example, if this was set to "foo" + * and sent to the homeserver "example.com" the complete room alias would be + * `#foo:example.com`. + * + * The complete room alias will become the canonical alias for the room and an + * `m.room.canonical_alias` event will be sent into the room. + */ + room_alias_name?: string; + + /** + * The room version to set for the room. If not provided, the homeserver is to use + * its configured default. If provided, the homeserver will return a 400 error with + * the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not support the room + * version. + */ + room_version?: string; + + /** + * If this is included, an + * [`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic) + * event with a `text/plain` mimetype will be sent into the room to indicate the + * topic for the room. This overwrites any + * [`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic) + * event in `initial_state`. + */ + topic?: string; + + /** + * The room's visibility in the server's + * [published room directory](https://spec.matrix.org/v1.18/client-server-api#published-room-directory). + * Defaults to `private`. + */ + visibility?: 'public' | 'private'; +} + +export namespace RoomCreateParams { + export interface InitialState { + /** + * The content of the event. + */ + content: unknown; + + /** + * The type of event to send. + */ + type: string; + + /** + * The state_key of the state event. Defaults to an empty string. + */ + state_key?: string; + } + + export interface Invite3pid { + /** + * The invitee's third-party identifier. + */ + address: string; + + /** + * An access token previously registered with the identity server. Servers can + * treat this as optional to distinguish between r0.5-compatible clients and this + * specification version. + */ + id_access_token: string; + + /** + * The hostname+port of the identity server which should be used for third-party + * identifier lookups. + */ + id_server: string; + + /** + * The kind of address being passed in the address field, for example `email` (see + * [the list of recognised values](https://spec.matrix.org/v1.18/appendices/#3pid-types)). + */ + medium: string; + } +} + +export interface RoomJoinParams { + /** + * Query param: The servers to attempt to join the room through. One of the servers + * must be participating in the room. + */ + via?: Array; + + /** + * Body param: Optional reason to be included as the `reason` on the subsequent + * membership event. + */ + reason?: string; + + /** + * Body param: A signature of an `m.third_party_invite` token to prove that this + * user owns a third-party identity which has been invited to the room. + */ + third_party_signed?: RoomJoinParams.ThirdPartySigned; +} + +export namespace RoomJoinParams { + /** + * A signature of an `m.third_party_invite` token to prove that this user owns a + * third-party identity which has been invited to the room. + */ + export interface ThirdPartySigned { + /** + * The state key of the m.third_party_invite event. + */ + token: string; + + /** + * The Matrix ID of the invitee. + */ + mxid: string; + + /** + * The Matrix ID of the user who issued the invite. + */ + sender: string; + + /** + * A signatures object containing a signature of the entire signed object. + */ + signatures: { [key: string]: { [key: string]: string } }; + } +} + +export interface RoomLeaveParams { + /** + * Optional reason to be included as the `reason` on the subsequent membership + * event. + */ + reason?: string; +} + +Rooms.AccountData = AccountData; +Rooms.BaseAccountData = BaseAccountData; +Rooms.State = State; +Rooms.BaseState = BaseState; +Rooms.Events = Events; +Rooms.BaseEvents = BaseEvents; + +export declare namespace Rooms { + export { + type RoomCreateResponse as RoomCreateResponse, + type RoomJoinResponse as RoomJoinResponse, + type RoomLeaveResponse as RoomLeaveResponse, + type RoomCreateParams as RoomCreateParams, + type RoomJoinParams as RoomJoinParams, + type RoomLeaveParams as RoomLeaveParams, + }; + + export { + AccountData as AccountData, + BaseAccountData as BaseAccountData, + type AccountDataRetrieveResponse as AccountDataRetrieveResponse, + type AccountDataUpdateResponse as AccountDataUpdateResponse, + type AccountDataRetrieveParams as AccountDataRetrieveParams, + type AccountDataUpdateParams as AccountDataUpdateParams, + }; + + export { + State as State, + BaseState as BaseState, + type StateRetrieveResponse as StateRetrieveResponse, + type StateListResponse as StateListResponse, + type StateRetrieveParams as StateRetrieveParams, + }; + + export { + Events as Events, + BaseEvents as BaseEvents, + type EventRetrieveResponse as EventRetrieveResponse, + type EventRetrieveParams as EventRetrieveParams, + }; +} diff --git a/src/resources/matrix/rooms/state.ts b/src/resources/matrix/rooms/state.ts new file mode 100644 index 00000000..870adf6d --- /dev/null +++ b/src/resources/matrix/rooms/state.ts @@ -0,0 +1,194 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class BaseState extends APIResource { + static override readonly _key: readonly ['matrix', 'rooms', 'state'] = Object.freeze([ + 'matrix', + 'rooms', + 'state', + ] as const); + + /** + * Looks up the contents of a state event in a room. If the user is joined to the + * room then the state is taken from the current state of the room. If the user has + * left the room then the state is taken from the state of the room when they left. + * + * @example + * ```ts + * const state = await client.matrix.rooms.state.retrieve( + * 'state_key', + * { + * roomId: '!636q39766251:example.com', + * eventType: 'm.room.name', + * }, + * ); + * ``` + */ + retrieve( + stateKey: string, + params: StateRetrieveParams, + options?: RequestOptions, + ): APIPromise { + const { roomId, eventType, ...query } = params; + return this._client.get(path`/_matrix/client/v3/rooms/${roomId}/state/${eventType}/${stateKey}`, { + query, + ...options, + }); + } + + /** + * Get the state events for the current state of a room. + * + * @example + * ```ts + * const states = await client.matrix.rooms.state.list( + * '!636q39766251:example.com', + * ); + * ``` + */ + list(roomID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/_matrix/client/v3/rooms/${roomID}/state`, options); + } +} +export class State extends BaseState {} + +export type StateRetrieveResponse = { [key: string]: unknown }; + +/** + * If the user is a member of the room this will be the current state of the room + * as a list of events. If the user has left the room then this will be the state + * of the room when they left as a list of events. + */ +export type StateListResponse = Array; + +export namespace StateListResponse { + /** + * The format used for events when they are returned from a homeserver to a client + * via the Client-Server API, or sent to an Application Service via the Application + * Services API. + */ + export interface StateListResponseItem { + /** + * The body of this event, as created by the client which sent it. + */ + content: unknown; + + /** + * The globally unique identifier for this event. + */ + event_id: string; + + /** + * Timestamp (in milliseconds since the unix epoch) on originating homeserver when + * this event was sent. + */ + origin_server_ts: number; + + /** + * The ID of the room associated with this event. + */ + room_id: string; + + /** + * Contains the fully-qualified ID of the user who sent this event. + */ + sender: string; + + /** + * The type of the event. + */ + type: string; + + /** + * Present if, and only if, this event is a _state_ event. The key making this + * piece of state unique in the room. Note that it is often an empty string. + * + * State keys starting with an `@` are reserved for referencing user IDs, such as + * room members. With the exception of a few events, state events set with a given + * user's ID as the state key MUST only be set by that user. + */ + state_key?: string; + + unsigned?: StateListResponseItem.Unsigned; + } + + export namespace StateListResponseItem { + export interface Unsigned { + /** + * The time in milliseconds that has elapsed since the event was sent. This field + * is generated by the local homeserver, and may be incorrect if the local time on + * at least one of the two servers is out of sync, which can cause the age to + * either be negative or greater than it actually is. + */ + age?: number; + + /** + * The room membership of the user making the request, at the time of the event. + * + * This property is the value of the `membership` property of the requesting user's + * [`m.room.member`](https://spec.matrix.org/v1.18/client-server-api#mroommember) + * state at the point of the event, including any changes caused by the event. If + * the user had yet to join the room at the time of the event (i.e, they have no + * `m.room.member` state), this property is set to `leave`. + * + * Homeservers SHOULD populate this property wherever practical, but they MAY omit + * it if necessary (for example, if calculating the value is expensive, servers + * might choose to only implement it in encrypted rooms). The property is _not_ + * normally populated in events pushed to application services via the application + * service transaction API (where there is no clear definition of "requesting + * user"). + */ + membership?: string; + + /** + * The previous `content` for this event. This field is generated by the local + * homeserver, and is only returned if the event is a state event, and the client + * has permission to see the previous content. + */ + prev_content?: unknown; + + redacted_because?: unknown; + + /** + * The client-supplied + * [transaction ID](https://spec.matrix.org/v1.18/client-server-api/#transaction-identifiers), + * for example, provided via + * `PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}`, if the client + * being given the event is the same one which sent it. + */ + transaction_id?: string; + } + } +} + +export interface StateRetrieveParams { + /** + * Path param: The room to look up the state in. + */ + roomId: string; + + /** + * Path param: The type of state to look up. + */ + eventType: string; + + /** + * Query param: The format to use for the returned data. `content` (the default) + * will return only the content of the state event. `event` will return the entire + * event in the usual format suitable for clients, including fields like event ID, + * sender and timestamp. + */ + format?: 'content' | 'event'; +} + +export declare namespace State { + export { + type StateRetrieveResponse as StateRetrieveResponse, + type StateListResponse as StateListResponse, + type StateRetrieveParams as StateRetrieveParams, + }; +} diff --git a/src/resources/matrix/users.ts b/src/resources/matrix/users.ts new file mode 100644 index 00000000..db908c70 --- /dev/null +++ b/src/resources/matrix/users.ts @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export * from './users/index'; diff --git a/src/resources/matrix/users/account-data.ts b/src/resources/matrix/users/account-data.ts new file mode 100644 index 00000000..4a009311 --- /dev/null +++ b/src/resources/matrix/users/account-data.ts @@ -0,0 +1,95 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class BaseAccountData extends APIResource { + static override readonly _key: readonly ['matrix', 'users', 'accountData'] = Object.freeze([ + 'matrix', + 'users', + 'accountData', + ] as const); + + /** + * Get some account data for the client. This config is only visible to the user + * that set the account data. + * + * @example + * ```ts + * const accountData = + * await client.matrix.users.accountData.retrieve( + * 'org.example.custom.config', + * { userId: '@alice:example.com' }, + * ); + * ``` + */ + retrieve(type: string, params: AccountDataRetrieveParams, options?: RequestOptions): APIPromise { + const { userId } = params; + return this._client.get(path`/_matrix/client/v3/user/${userId}/account_data/${type}`, options); + } + + /** + * Set some account data for the client. This config is only visible to the user + * that set the account data. The config will be available to clients through the + * top-level `account_data` field in the homeserver response to + * [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync). + * + * @example + * ```ts + * const accountData = + * await client.matrix.users.accountData.update( + * 'org.example.custom.config', + * { + * userId: '@alice:example.com', + * body: { + * custom_account_data_key: 'custom_config_value', + * }, + * }, + * ); + * ``` + */ + update(type: string, params: AccountDataUpdateParams, options?: RequestOptions): APIPromise { + const { userId, body } = params; + return this._client.put(path`/_matrix/client/v3/user/${userId}/account_data/${type}`, { + body: body, + ...options, + }); + } +} +export class AccountData extends BaseAccountData {} + +export type AccountDataRetrieveResponse = unknown; + +export type AccountDataUpdateResponse = unknown; + +export interface AccountDataRetrieveParams { + /** + * The ID of the user to get account data for. The access token must be authorized + * to make requests for this user ID. + */ + userId: string; +} + +export interface AccountDataUpdateParams { + /** + * Path param: The ID of the user to set account data for. The access token must be + * authorized to make requests for this user ID. + */ + userId: string; + + /** + * Body param + */ + body: unknown; +} + +export declare namespace AccountData { + export { + type AccountDataRetrieveResponse as AccountDataRetrieveResponse, + type AccountDataUpdateResponse as AccountDataUpdateResponse, + type AccountDataRetrieveParams as AccountDataRetrieveParams, + type AccountDataUpdateParams as AccountDataUpdateParams, + }; +} diff --git a/src/resources/matrix/users/index.ts b/src/resources/matrix/users/index.ts new file mode 100644 index 00000000..f7d0405c --- /dev/null +++ b/src/resources/matrix/users/index.ts @@ -0,0 +1,11 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + AccountData, + BaseAccountData, + type AccountDataRetrieveResponse, + type AccountDataUpdateResponse, + type AccountDataRetrieveParams, + type AccountDataUpdateParams, +} from './account-data'; +export { Users, BaseUsers, type UserRetrieveProfileResponse } from './users'; diff --git a/src/resources/matrix/users/users.ts b/src/resources/matrix/users/users.ts new file mode 100644 index 00000000..8fd4e3a6 --- /dev/null +++ b/src/resources/matrix/users/users.ts @@ -0,0 +1,71 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as AccountDataAPI from './account-data'; +import { + AccountData, + AccountDataRetrieveParams, + AccountDataRetrieveResponse, + AccountDataUpdateParams, + AccountDataUpdateResponse, + BaseAccountData, +} from './account-data'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +export class BaseUsers extends APIResource { + static override readonly _key: readonly ['matrix', 'users'] = Object.freeze(['matrix', 'users'] as const); + + /** + * Get the complete profile for a user. + * + * @example + * ```ts + * const response = await client.matrix.users.retrieveProfile( + * '@alice:example.com', + * ); + * ``` + */ + retrieveProfile(userID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/_matrix/client/v3/profile/${userID}`, options); + } +} +export class Users extends BaseUsers { + accountData: AccountDataAPI.AccountData = new AccountDataAPI.AccountData(this._client); +} + +export interface UserRetrieveProfileResponse { + /** + * The user's avatar URL if they have set one, otherwise not present. + */ + avatar_url?: string; + + /** + * The user's display name if they have set one, otherwise not present. + */ + displayname?: string; + + /** + * The user's time zone. + */ + 'm.tz'?: string; + + [k: string]: unknown; +} + +Users.AccountData = AccountData; +Users.BaseAccountData = BaseAccountData; + +export declare namespace Users { + export { type UserRetrieveProfileResponse as UserRetrieveProfileResponse }; + + export { + AccountData as AccountData, + BaseAccountData as BaseAccountData, + type AccountDataRetrieveResponse as AccountDataRetrieveResponse, + type AccountDataUpdateResponse as AccountDataUpdateResponse, + type AccountDataRetrieveParams as AccountDataRetrieveParams, + type AccountDataUpdateParams as AccountDataUpdateParams, + }; +} diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 63fda684..82735239 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -2,6 +2,233 @@ import { CursorNoLimit, CursorSearch } from '../core/pagination'; +export interface AppStateSnapshot { + /** + * Encrypted messaging setup status. + */ + e2ee: AppStateSnapshot.E2ee; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppStateSnapshot.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: AppStateSnapshot.Verification; +} + +export namespace AppStateSnapshot { + /** + * Encrypted messaging setup status. + */ + export interface E2ee { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpCode: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2ee.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryCodeGeneratedAt?: number; + } + + export namespace E2ee { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryCode: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array< + 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' + >; + + /** + * Current trusted-device verification state. + */ + state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * User ID that started verification. + */ + from?: string; + + /** + * Device that started verification. + */ + fromDevice?: string; + + /** + * Other device participating in verification. + */ + otherDevice?: string; + + /** + * QR code payload to display for verification. + */ + qrData?: string; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.Sas; + + /** + * Whether emoji comparison is available. + */ + supportsSAS?: boolean; + + /** + * Whether QR code verification is available. + */ + supportsScanQRCode?: boolean; + + /** + * Verification ID to pass in verification action paths. + */ + verificationID?: string; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface Sas { + /** + * Number sequence to compare on both devices. + */ + decimals: string; + + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + } + } +} + export interface Attachment { /** * Attachment type. diff --git a/src/tree-shakable.ts b/src/tree-shakable.ts index f7b9ba0b..4df08909 100644 --- a/src/tree-shakable.ts +++ b/src/tree-shakable.ts @@ -18,11 +18,11 @@ type InferClientStructure = * * @example * ```ts - * import { Accounts } from `@beeper/desktop-api/resources/accounts`; + * import { App } from `@beeper/desktop-api/resources/app`; * import { createClient } from `@beeper/desktop-api/tree-shakable`; * * const client = createClient({ - * resources: [Accounts], + * resources: [App], * }); * ``` */ diff --git a/tests/api-resources/app/app.test.ts b/tests/api-resources/app/app.test.ts new file mode 100644 index 00000000..b501ff17 --- /dev/null +++ b/tests/api-resources/app/app.test.ts @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseApp } from '@beeper/desktop-api/resources/app/app'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseApp], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: BaseApp }>) => { + test('status', async () => { + const responsePromise = client.app.status(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource app', () => runTests(client)); +describe('resource app (tree shakable, base)', () => runTests(partialClient)); diff --git a/tests/api-resources/app/e2ee/recovery-code/recovery-code.test.ts b/tests/api-resources/app/e2ee/recovery-code/recovery-code.test.ts new file mode 100644 index 00000000..e433cef7 --- /dev/null +++ b/tests/api-resources/app/e2ee/recovery-code/recovery-code.test.ts @@ -0,0 +1,55 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { E2ee } from '@beeper/desktop-api/resources/app/e2ee/e2ee'; +import { BaseRecoveryCode } from '@beeper/desktop-api/resources/app/e2ee/recovery-code/recovery-code'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseRecoveryCode], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [E2ee], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { recoveryCode: BaseRecoveryCode } } }>) => { + test('markBackedUp', async () => { + const responsePromise = client.app.e2ee.recoveryCode.markBackedUp(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('verify: only required params', async () => { + const responsePromise = client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('verify: required and optional params', async () => { + const response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' }); + }); +}; +describe('resource recoveryCode', () => runTests(client)); +describe('resource recoveryCode (tree shakable, base)', () => runTests(partialClient)); +describe('resource recoveryCode (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/e2ee/recovery-code/reset.test.ts b/tests/api-resources/app/e2ee/recovery-code/reset.test.ts new file mode 100644 index 00000000..b2985000 --- /dev/null +++ b/tests/api-resources/app/e2ee/recovery-code/reset.test.ts @@ -0,0 +1,67 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { RecoveryCode } from '@beeper/desktop-api/resources/app/e2ee/recovery-code/recovery-code'; +import { BaseReset } from '@beeper/desktop-api/resources/app/e2ee/recovery-code/reset'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseReset], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [RecoveryCode], +}); + +const runTests = ( + client: PartialBeeperDesktop<{ app: { e2ee: { recoveryCode: { reset: BaseReset } } } }>, +) => { + test('create', async () => { + const responsePromise = client.app.e2ee.recoveryCode.reset.create(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.app.e2ee.recoveryCode.reset.create( + { recoveryCode: 'recoveryCode' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); + + test('confirm: only required params', async () => { + const responsePromise = client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('confirm: required and optional params', async () => { + const response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' }); + }); +}; +describe('resource reset', () => runTests(client)); +describe('resource reset (tree shakable, base)', () => runTests(partialClient)); +describe('resource reset (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/e2ee/verification/qr.test.ts b/tests/api-resources/app/e2ee/verification/qr.test.ts new file mode 100644 index 00000000..681906e4 --- /dev/null +++ b/tests/api-resources/app/e2ee/verification/qr.test.ts @@ -0,0 +1,55 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseQr } from '@beeper/desktop-api/resources/app/e2ee/verification/qr'; +import { Verification } from '@beeper/desktop-api/resources/app/e2ee/verification/verification'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseQr], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Verification], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: { qr: BaseQr } } } }>) => { + test('confirmScanned', async () => { + const responsePromise = client.app.e2ee.verification.qr.confirmScanned('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('scan: only required params', async () => { + const responsePromise = client.app.e2ee.verification.qr.scan({ data: 'x' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('scan: required and optional params', async () => { + const response = await client.app.e2ee.verification.qr.scan({ data: 'x' }); + }); +}; +describe('resource qr', () => runTests(client)); +describe('resource qr (tree shakable, base)', () => runTests(partialClient)); +describe('resource qr (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/e2ee/verification/sas.test.ts b/tests/api-resources/app/e2ee/verification/sas.test.ts new file mode 100644 index 00000000..d800bf63 --- /dev/null +++ b/tests/api-resources/app/e2ee/verification/sas.test.ts @@ -0,0 +1,51 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseSas } from '@beeper/desktop-api/resources/app/e2ee/verification/sas'; +import { Verification } from '@beeper/desktop-api/resources/app/e2ee/verification/verification'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseSas], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Verification], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: { sas: BaseSas } } } }>) => { + test('confirm', async () => { + const responsePromise = client.app.e2ee.verification.sas.confirm('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('start', async () => { + const responsePromise = client.app.e2ee.verification.sas.start('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource sas', () => runTests(client)); +describe('resource sas (tree shakable, base)', () => runTests(partialClient)); +describe('resource sas (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/e2ee/verification/verification.test.ts b/tests/api-resources/app/e2ee/verification/verification.test.ts new file mode 100644 index 00000000..97dd2436 --- /dev/null +++ b/tests/api-resources/app/e2ee/verification/verification.test.ts @@ -0,0 +1,80 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { E2ee } from '@beeper/desktop-api/resources/app/e2ee/e2ee'; +import { BaseVerification } from '@beeper/desktop-api/resources/app/e2ee/verification/verification'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseVerification], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [E2ee], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: BaseVerification } } }>) => { + test('create', async () => { + const responsePromise = client.app.e2ee.verification.create(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.app.e2ee.verification.create({ userID: 'userID' }, { path: '/_stainless_unknown_path' }), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); + + test('accept', async () => { + const responsePromise = client.app.e2ee.verification.accept('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('cancel', async () => { + const responsePromise = client.app.e2ee.verification.cancel('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('cancel: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.app.e2ee.verification.cancel( + 'x', + { code: 'code', reason: 'reason' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); +}; +describe('resource verification', () => runTests(client)); +describe('resource verification (tree shakable, base)', () => runTests(partialClient)); +describe('resource verification (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/login.test.ts b/tests/api-resources/app/login.test.ts new file mode 100644 index 00000000..d0458efb --- /dev/null +++ b/tests/api-resources/app/login.test.ts @@ -0,0 +1,95 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { App } from '@beeper/desktop-api/resources/app/app'; +import { BaseLogin } from '@beeper/desktop-api/resources/app/login'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseLogin], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [App], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { login: BaseLogin } }>) => { + test('email: only required params', async () => { + const responsePromise = client.app.login.email({ email: 'dev@stainless.com', request: 'request' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('email: required and optional params', async () => { + const response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' }); + }); + + test('register: only required params', async () => { + const responsePromise = client.app.login.register({ + acceptTerms: true, + leadToken: 'leadToken', + request: 'request', + username: 'x', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('register: required and optional params', async () => { + const response = await client.app.login.register({ + acceptTerms: true, + leadToken: 'leadToken', + request: 'request', + username: 'x', + }); + }); + + test('response: only required params', async () => { + const responsePromise = client.app.login.response({ request: 'request', response: 'response' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('response: required and optional params', async () => { + const response = await client.app.login.response({ request: 'request', response: 'response' }); + }); + + test('start', async () => { + const responsePromise = client.app.login.start(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource login', () => runTests(client)); +describe('resource login (tree shakable, base)', () => runTests(partialClient)); +describe('resource login (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/bridges.test.ts b/tests/api-resources/bridges.test.ts new file mode 100644 index 00000000..51c139fc --- /dev/null +++ b/tests/api-resources/bridges.test.ts @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseBridges } from '@beeper/desktop-api/resources/bridges'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseBridges], +}); + +const runTests = (client: PartialBeeperDesktop<{ bridges: BaseBridges }>) => { + test('list', async () => { + const responsePromise = client.bridges.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource bridges', () => runTests(client)); +describe('resource bridges (tree shakable, base)', () => runTests(partialClient)); diff --git a/tests/api-resources/matrix/bridges/auth.test.ts b/tests/api-resources/matrix/bridges/auth.test.ts new file mode 100644 index 00000000..30a7964c --- /dev/null +++ b/tests/api-resources/matrix/bridges/auth.test.ts @@ -0,0 +1,166 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseAuth } from '@beeper/desktop-api/resources/matrix/bridges/auth'; +import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseAuth], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Bridges], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { bridges: { auth: BaseAuth } } }>) => { + test('listFlows', async () => { + const responsePromise = client.matrix.bridges.auth.listFlows('bridgeID'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('listLogins', async () => { + const responsePromise = client.matrix.bridges.auth.listLogins('bridgeID'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('logout: only required params', async () => { + const responsePromise = client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', { + bridgeID: 'bridgeID', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('logout: required and optional params', async () => { + const response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', { + bridgeID: 'bridgeID', + }); + }); + + test('startLogin: only required params', async () => { + const responsePromise = client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('startLogin: required and optional params', async () => { + const response = await client.matrix.bridges.auth.startLogin('qr', { + bridgeID: 'bridgeID', + login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', + }); + }); + + test('submitCookies: only required params', async () => { + const responsePromise = client.matrix.bridges.auth.submitCookies('stepID', { + bridgeID: 'bridgeID', + loginProcessID: 'loginProcessID', + body: { foo: 'string' }, + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('submitCookies: required and optional params', async () => { + const response = await client.matrix.bridges.auth.submitCookies('stepID', { + bridgeID: 'bridgeID', + loginProcessID: 'loginProcessID', + body: { foo: 'string' }, + }); + }); + + test('submitUserInput: only required params', async () => { + const responsePromise = client.matrix.bridges.auth.submitUserInput('stepID', { + bridgeID: 'bridgeID', + loginProcessID: 'loginProcessID', + body: { foo: 'string' }, + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('submitUserInput: required and optional params', async () => { + const response = await client.matrix.bridges.auth.submitUserInput('stepID', { + bridgeID: 'bridgeID', + loginProcessID: 'loginProcessID', + body: { foo: 'string' }, + }); + }); + + test('waitForStep: only required params', async () => { + const responsePromise = client.matrix.bridges.auth.waitForStep('stepID', { + bridgeID: 'bridgeID', + loginProcessID: 'loginProcessID', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('waitForStep: required and optional params', async () => { + const response = await client.matrix.bridges.auth.waitForStep('stepID', { + bridgeID: 'bridgeID', + loginProcessID: 'loginProcessID', + }); + }); + + test('whoami', async () => { + const responsePromise = client.matrix.bridges.auth.whoami('bridgeID'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource auth', () => runTests(client)); +describe('resource auth (tree shakable, base)', () => runTests(partialClient)); +describe('resource auth (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/bridges/capabilities.test.ts b/tests/api-resources/matrix/bridges/capabilities.test.ts new file mode 100644 index 00000000..a24bbb1a --- /dev/null +++ b/tests/api-resources/matrix/bridges/capabilities.test.ts @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; +import { BaseCapabilities } from '@beeper/desktop-api/resources/matrix/bridges/capabilities'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseCapabilities], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Bridges], +}); + +const runTests = ( + client: PartialBeeperDesktop<{ matrix: { bridges: { capabilities: BaseCapabilities } } }>, +) => { + test('retrieve', async () => { + const responsePromise = client.matrix.bridges.capabilities.retrieve('bridgeID'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource capabilities', () => runTests(client)); +describe('resource capabilities (tree shakable, base)', () => runTests(partialClient)); +describe('resource capabilities (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/bridges/contacts.test.ts b/tests/api-resources/matrix/bridges/contacts.test.ts new file mode 100644 index 00000000..1e669c23 --- /dev/null +++ b/tests/api-resources/matrix/bridges/contacts.test.ts @@ -0,0 +1,51 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; +import { BaseContacts } from '@beeper/desktop-api/resources/matrix/bridges/contacts'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseContacts], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Bridges], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { bridges: { contacts: BaseContacts } } }>) => { + test('list', async () => { + const responsePromise = client.matrix.bridges.contacts.list('bridgeID'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.matrix.bridges.contacts.list( + 'bridgeID', + { login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); +}; +describe('resource contacts', () => runTests(client)); +describe('resource contacts (tree shakable, base)', () => runTests(partialClient)); +describe('resource contacts (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/bridges/rooms.test.ts b/tests/api-resources/matrix/bridges/rooms.test.ts new file mode 100644 index 00000000..e574d381 --- /dev/null +++ b/tests/api-resources/matrix/bridges/rooms.test.ts @@ -0,0 +1,74 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; +import { BaseRooms } from '@beeper/desktop-api/resources/matrix/bridges/rooms'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseRooms], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Bridges], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { bridges: { rooms: BaseRooms } } }>) => { + test('createDm: only required params', async () => { + const responsePromise = client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('createDm: required and optional params', async () => { + const response = await client.matrix.bridges.rooms.createDm('identifier', { + bridgeID: 'bridgeID', + login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', + }); + }); + + test('createGroup: only required params', async () => { + const responsePromise = client.matrix.bridges.rooms.createGroup('groupType', { bridgeID: 'bridgeID' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('createGroup: required and optional params', async () => { + const response = await client.matrix.bridges.rooms.createGroup('groupType', { + bridgeID: 'bridgeID', + login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', + avatar: { url: 'url' }, + disappear: { timer: 0, type: 'type' }, + name: { name: 'name' }, + parent: {}, + participants: ['string'], + room_id: 'room_id', + topic: { topic: 'topic' }, + type: 'channel', + username: 'username', + }); + }); +}; +describe('resource rooms', () => runTests(client)); +describe('resource rooms (tree shakable, base)', () => runTests(partialClient)); +describe('resource rooms (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/bridges/users.test.ts b/tests/api-resources/matrix/bridges/users.test.ts new file mode 100644 index 00000000..1eb0476a --- /dev/null +++ b/tests/api-resources/matrix/bridges/users.test.ts @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; +import { BaseUsers } from '@beeper/desktop-api/resources/matrix/bridges/users'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseUsers], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Bridges], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { bridges: { users: BaseUsers } } }>) => { + test('resolve: only required params', async () => { + const responsePromise = client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('resolve: required and optional params', async () => { + const response = await client.matrix.bridges.users.resolve('identifier', { + bridgeID: 'bridgeID', + login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', + }); + }); + + test('search', async () => { + const responsePromise = client.matrix.bridges.users.search('bridgeID'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('search: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.matrix.bridges.users.search( + 'bridgeID', + { login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', query: 'query' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); +}; +describe('resource users', () => runTests(client)); +describe('resource users (tree shakable, base)', () => runTests(partialClient)); +describe('resource users (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/rooms/account-data.test.ts b/tests/api-resources/matrix/rooms/account-data.test.ts new file mode 100644 index 00000000..da07e7ec --- /dev/null +++ b/tests/api-resources/matrix/rooms/account-data.test.ts @@ -0,0 +1,73 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseAccountData } from '@beeper/desktop-api/resources/matrix/rooms/account-data'; +import { Rooms } from '@beeper/desktop-api/resources/matrix/rooms/rooms'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseAccountData], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Rooms], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: { accountData: BaseAccountData } } }>) => { + test('retrieve: only required params', async () => { + const responsePromise = client.matrix.rooms.accountData.retrieve('org.example.custom.room.config', { + userId: '@alice:example.com', + roomId: '!726s6s6q:example.com', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.matrix.rooms.accountData.retrieve('org.example.custom.room.config', { + userId: '@alice:example.com', + roomId: '!726s6s6q:example.com', + }); + }); + + test('update: only required params', async () => { + const responsePromise = client.matrix.rooms.accountData.update('org.example.custom.room.config', { + userId: '@alice:example.com', + roomId: '!726s6s6q:example.com', + body: { custom_account_data_key: 'custom_account_data_value' }, + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update: required and optional params', async () => { + const response = await client.matrix.rooms.accountData.update('org.example.custom.room.config', { + userId: '@alice:example.com', + roomId: '!726s6s6q:example.com', + body: { custom_account_data_key: 'custom_account_data_value' }, + }); + }); +}; +describe('resource accountData', () => runTests(client)); +describe('resource accountData (tree shakable, base)', () => runTests(partialClient)); +describe('resource accountData (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/rooms/events.test.ts b/tests/api-resources/matrix/rooms/events.test.ts new file mode 100644 index 00000000..81bb6e08 --- /dev/null +++ b/tests/api-resources/matrix/rooms/events.test.ts @@ -0,0 +1,48 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseEvents } from '@beeper/desktop-api/resources/matrix/rooms/events'; +import { Rooms } from '@beeper/desktop-api/resources/matrix/rooms/rooms'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseEvents], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Rooms], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: { events: BaseEvents } } }>) => { + test('retrieve: only required params', async () => { + const responsePromise = client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', { + roomId: '!636q39766251:matrix.org', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', { + roomId: '!636q39766251:matrix.org', + }); + }); +}; +describe('resource events', () => runTests(client)); +describe('resource events (tree shakable, base)', () => runTests(partialClient)); +describe('resource events (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/rooms/rooms.test.ts b/tests/api-resources/matrix/rooms/rooms.test.ts new file mode 100644 index 00000000..1eb928db --- /dev/null +++ b/tests/api-resources/matrix/rooms/rooms.test.ts @@ -0,0 +1,62 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Matrix } from '@beeper/desktop-api/resources/matrix/matrix'; +import { BaseRooms } from '@beeper/desktop-api/resources/matrix/rooms/rooms'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseRooms], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Matrix], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: BaseRooms } }>) => { + test('create', async () => { + const responsePromise = client.matrix.rooms.create({}); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('join', async () => { + const responsePromise = client.matrix.rooms.join('!monkeys:matrix.org', {}); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('leave', async () => { + const responsePromise = client.matrix.rooms.leave('!nkl290a:matrix.org', {}); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource rooms', () => runTests(client)); +describe('resource rooms (tree shakable, base)', () => runTests(partialClient)); +describe('resource rooms (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/rooms/state.test.ts b/tests/api-resources/matrix/rooms/state.test.ts new file mode 100644 index 00000000..b44f7931 --- /dev/null +++ b/tests/api-resources/matrix/rooms/state.test.ts @@ -0,0 +1,62 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Rooms } from '@beeper/desktop-api/resources/matrix/rooms/rooms'; +import { BaseState } from '@beeper/desktop-api/resources/matrix/rooms/state'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseState], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Rooms], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: { state: BaseState } } }>) => { + test('retrieve: only required params', async () => { + const responsePromise = client.matrix.rooms.state.retrieve('state_key', { + roomId: '!636q39766251:example.com', + eventType: 'm.room.name', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.matrix.rooms.state.retrieve('state_key', { + roomId: '!636q39766251:example.com', + eventType: 'm.room.name', + format: 'content', + }); + }); + + test('list', async () => { + const responsePromise = client.matrix.rooms.state.list('!636q39766251:example.com'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource state', () => runTests(client)); +describe('resource state (tree shakable, base)', () => runTests(partialClient)); +describe('resource state (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/users/account-data.test.ts b/tests/api-resources/matrix/users/account-data.test.ts new file mode 100644 index 00000000..21210e6f --- /dev/null +++ b/tests/api-resources/matrix/users/account-data.test.ts @@ -0,0 +1,69 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseAccountData } from '@beeper/desktop-api/resources/matrix/users/account-data'; +import { Users } from '@beeper/desktop-api/resources/matrix/users/users'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseAccountData], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Users], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { users: { accountData: BaseAccountData } } }>) => { + test('retrieve: only required params', async () => { + const responsePromise = client.matrix.users.accountData.retrieve('org.example.custom.config', { + userId: '@alice:example.com', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.matrix.users.accountData.retrieve('org.example.custom.config', { + userId: '@alice:example.com', + }); + }); + + test('update: only required params', async () => { + const responsePromise = client.matrix.users.accountData.update('org.example.custom.config', { + userId: '@alice:example.com', + body: { custom_account_data_key: 'custom_config_value' }, + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('update: required and optional params', async () => { + const response = await client.matrix.users.accountData.update('org.example.custom.config', { + userId: '@alice:example.com', + body: { custom_account_data_key: 'custom_config_value' }, + }); + }); +}; +describe('resource accountData', () => runTests(client)); +describe('resource accountData (tree shakable, base)', () => runTests(partialClient)); +describe('resource accountData (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/users/users.test.ts b/tests/api-resources/matrix/users/users.test.ts new file mode 100644 index 00000000..e38005c5 --- /dev/null +++ b/tests/api-resources/matrix/users/users.test.ts @@ -0,0 +1,40 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Matrix } from '@beeper/desktop-api/resources/matrix/matrix'; +import { BaseUsers } from '@beeper/desktop-api/resources/matrix/users/users'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseUsers], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Matrix], +}); + +const runTests = (client: PartialBeeperDesktop<{ matrix: { users: BaseUsers } }>) => { + test('retrieveProfile', async () => { + const responsePromise = client.matrix.users.retrieveProfile('@alice:example.com'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource users', () => runTests(client)); +describe('resource users (tree shakable, base)', () => runTests(partialClient)); +describe('resource users (tree shakable, subresource)', () => runTests(parentPartialClient)); From 3145ba867d02ea330ffcbad609f4d638bc99cf91 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 May 2026 20:30:19 +0000 Subject: [PATCH 06/17] Validate route auth handling --- .stats.yml | 4 ++-- packages/mcp-server/manifest.json | 4 ++-- packages/mcp-server/src/local-docs-search.ts | 2 +- src/client.ts | 19 ++++++++----------- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/.stats.yml b/.stats.yml index b63d20d3..c9bf663e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 72 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-de1370e6a3183044fa135a886d2ee8f779d5e86228cdbd503d553b4c13cc7cbe.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-81a39fdda33b337c5047b92f24bb2216150cba5507f9b66d3ef6a324e2b08e92.yml openapi_spec_hash: 30b435d7585d8b6951610e7147369779 -config_hash: 683b13ea6fb6aa9d6b1b8814cca24f1c +config_hash: 6b409dea8089a8bfc72ed9919dc1d0bb diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index d59e1349..df87680b 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -29,8 +29,8 @@ "user_config": { "BEEPER_ACCESS_TOKEN": { "title": "access_token", - "description": "Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations.", - "required": true, + "description": "Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations.", + "required": false, "type": "string" } }, diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 0d902a84..2282ce61 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -3382,7 +3382,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'cli', content: - "# Beeper Desktop CLI\n\nThe official CLI for the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/).\n\n\n\n## Installation\n\n### Installing with Homebrew\n\n~~~sh\nbrew install beeper/tap/beeper-desktop-cli\n~~~\n\n### Installing with Go\n\nTo test or install the CLI locally, you need [Go](https://go.dev/doc/install) version 1.22 or later installed.\n\n~~~sh\ngo install 'github.com/beeper/desktop-api-cli/cmd/beeper-desktop-cli@latest'\n~~~\n\nOnce you have run `go install`, the binary is placed in your Go bin directory:\n\n- **Default location**: `$HOME/go/bin` (or `$GOPATH/bin` if GOPATH is set)\n- **Check your path**: Run `go env GOPATH` to see the base directory\n\nIf commands aren't found after installation, add the Go bin directory to your PATH:\n\n~~~sh\n# Add to your shell profile (.zshrc, .bashrc, etc.)\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n~~~\n\n\n\n### Running Locally\n\nAfter cloning the git repository for this project, you can use the\n`scripts/run` script to run the tool locally:\n\n~~~sh\n./scripts/run args...\n~~~\n\n## Usage\n\nThe CLI follows a resource-based command structure:\n\n~~~sh\nbeeper-desktop-cli [resource] [flags...]\n~~~\n\n~~~sh\nbeeper-desktop-cli chats search \\\n --access-token 'My Access Token' \\\n --account-id matrix \\\n --account-id discordgo \\\n --account-id local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --include-muted \\\n --limit 3 \\\n --type single\n~~~\n\nFor details about specific commands, use the `--help` flag.\n\n### Environment variables\n\n| Environment variable | Description | Required |\n| --------------------- | ----------------------------------------------------------------------------------------------------- | -------- |\n| `BEEPER_ACCESS_TOKEN` | Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations. | yes |\n\n### Global flags\n\n- `--access-token` - Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations. (can also be set with `BEEPER_ACCESS_TOKEN` env var)\n- `--help` - Show command line usage\n- `--debug` - Enable debug logging (includes HTTP request/response details)\n- `--version`, `-v` - Show the CLI version\n- `--base-url` - Use a custom API backend URL\n- `--format` - Change the output format (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--format-error` - Change the output format for errors (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--transform` - Transform the data output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n- `--transform-error` - Transform the error output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n\n### Passing files as arguments\n\nTo pass files to your API, you can use the `@myfile.ext` syntax:\n\n~~~bash\nbeeper-desktop-cli --arg @abe.jpg\n~~~\n\nFiles can also be passed inside JSON or YAML blobs:\n\n~~~bash\nbeeper-desktop-cli --arg '{image: \"@abe.jpg\"}'\n# Equivalent:\nbeeper-desktop-cli < --username '\\@abe'\n~~~\n\n#### Explicit encoding\n\nFor JSON endpoints, the CLI tool does filetype sniffing to determine whether the\nfile contents should be sent as a string literal (for plain text files) or as a\nbase64-encoded string literal (for binary files). If you need to explicitly send\nthe file as either plain text or base64-encoded data, you can use\n`@file://myfile.txt` (for string encoding) or `@data://myfile.dat` (for\nbase64-encoding). Note that absolute paths will begin with `@file://` or\n`@data://`, followed by a third `/` (for example, `@file:///tmp/file.txt`).\n\n~~~bash\nbeeper-desktop-cli --arg @data://file.txt\n~~~\n\n## Linking different Go SDK versions\n\nYou can link the CLI against a different version of the Beeper Desktop Go SDK\nfor development purposes using the `./scripts/link` script.\n\nTo link to a specific version from a repository (version can be a branch,\ngit tag, or commit hash):\n\n~~~bash\n./scripts/link github.com/org/repo@version\n~~~\n\nTo link to a local copy of the SDK:\n\n~~~bash\n./scripts/link ../path/to/beeperdesktopapi-go\n~~~\n\nIf you run the link script without any arguments, it will default to `../beeperdesktopapi-go`.\n", + "# Beeper Desktop CLI\n\nThe official CLI for the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/).\n\n\n\n## Installation\n\n### Installing with Homebrew\n\n~~~sh\nbrew install beeper/tap/beeper-desktop-cli\n~~~\n\n### Installing with Go\n\nTo test or install the CLI locally, you need [Go](https://go.dev/doc/install) version 1.22 or later installed.\n\n~~~sh\ngo install 'github.com/beeper/desktop-api-cli/cmd/beeper-desktop-cli@latest'\n~~~\n\nOnce you have run `go install`, the binary is placed in your Go bin directory:\n\n- **Default location**: `$HOME/go/bin` (or `$GOPATH/bin` if GOPATH is set)\n- **Check your path**: Run `go env GOPATH` to see the base directory\n\nIf commands aren't found after installation, add the Go bin directory to your PATH:\n\n~~~sh\n# Add to your shell profile (.zshrc, .bashrc, etc.)\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n~~~\n\n\n\n### Running Locally\n\nAfter cloning the git repository for this project, you can use the\n`scripts/run` script to run the tool locally:\n\n~~~sh\n./scripts/run args...\n~~~\n\n## Usage\n\nThe CLI follows a resource-based command structure:\n\n~~~sh\nbeeper-desktop-cli [resource] [flags...]\n~~~\n\n~~~sh\nbeeper-desktop-cli chats search \\\n --access-token 'My Access Token' \\\n --account-id matrix \\\n --account-id discordgo \\\n --account-id local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --include-muted \\\n --limit 3 \\\n --type single\n~~~\n\nFor details about specific commands, use the `--help` flag.\n\n### Environment variables\n\n| Environment variable | Description | Required | Default value |\n| --------------------- | --------------------------------------------------------------------------------------------------------------- | -------- | ------------- |\n| `BEEPER_ACCESS_TOKEN` | Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. | no | `null` |\n\n### Global flags\n\n- `--access-token` - Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. (can also be set with `BEEPER_ACCESS_TOKEN` env var)\n- `--help` - Show command line usage\n- `--debug` - Enable debug logging (includes HTTP request/response details)\n- `--version`, `-v` - Show the CLI version\n- `--base-url` - Use a custom API backend URL\n- `--format` - Change the output format (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--format-error` - Change the output format for errors (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--transform` - Transform the data output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n- `--transform-error` - Transform the error output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n\n### Passing files as arguments\n\nTo pass files to your API, you can use the `@myfile.ext` syntax:\n\n~~~bash\nbeeper-desktop-cli --arg @abe.jpg\n~~~\n\nFiles can also be passed inside JSON or YAML blobs:\n\n~~~bash\nbeeper-desktop-cli --arg '{image: \"@abe.jpg\"}'\n# Equivalent:\nbeeper-desktop-cli < --username '\\@abe'\n~~~\n\n#### Explicit encoding\n\nFor JSON endpoints, the CLI tool does filetype sniffing to determine whether the\nfile contents should be sent as a string literal (for plain text files) or as a\nbase64-encoded string literal (for binary files). If you need to explicitly send\nthe file as either plain text or base64-encoded data, you can use\n`@file://myfile.txt` (for string encoding) or `@data://myfile.dat` (for\nbase64-encoding). Note that absolute paths will begin with `@file://` or\n`@data://`, followed by a third `/` (for example, `@file:///tmp/file.txt`).\n\n~~~bash\nbeeper-desktop-cli --arg @data://file.txt\n~~~\n\n## Linking different Go SDK versions\n\nYou can link the CLI against a different version of the Beeper Desktop Go SDK\nfor development purposes using the `./scripts/link` script.\n\nTo link to a specific version from a repository (version can be a branch,\ngit tag, or commit hash):\n\n~~~bash\n./scripts/link github.com/org/repo@version\n~~~\n\nTo link to a local copy of the SDK:\n\n~~~bash\n./scripts/link ../path/to/beeperdesktopapi-go\n~~~\n\nIf you run the link script without any arguments, it will default to `../beeperdesktopapi-go`.\n", }, { language: 'go', diff --git a/src/client.ts b/src/client.ts index efaa2a81..50880e47 100644 --- a/src/client.ts +++ b/src/client.ts @@ -96,9 +96,9 @@ import { isEmptyObj } from './internal/utils/values'; export interface ClientOptions { /** - * Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for all API operations. + * Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. */ - accessToken?: string | undefined; + accessToken?: string | null | undefined; /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" @@ -173,7 +173,7 @@ export interface ClientOptions { * Base class for Beeper Desktop API clients. */ export class BaseBeeperDesktop { - accessToken: string; + accessToken: string | null; baseURL: string; maxRetries: number; @@ -190,7 +190,7 @@ export class BaseBeeperDesktop { /** * API Client for interfacing with the Beeper Desktop API. * - * @param {string | undefined} [opts.accessToken=process.env['BEEPER_ACCESS_TOKEN'] ?? undefined] + * @param {string | null | undefined} [opts.accessToken=process.env['BEEPER_ACCESS_TOKEN'] ?? null] * @param {string} [opts.baseURL=process.env['BEEPER_BASE_URL'] ?? http://localhost:23373] - Override the default base URL for the API. * @param {number} [opts.timeout=30 seconds] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. @@ -201,15 +201,9 @@ export class BaseBeeperDesktop { */ constructor({ baseURL = readEnv('BEEPER_BASE_URL'), - accessToken = readEnv('BEEPER_ACCESS_TOKEN'), + accessToken = readEnv('BEEPER_ACCESS_TOKEN') ?? null, ...opts }: ClientOptions = {}) { - if (accessToken === undefined) { - throw new Errors.BeeperDesktopError( - "The BEEPER_ACCESS_TOKEN environment variable is missing or empty; either provide it, or instantiate the BeeperDesktop client with an accessToken option, like new BeeperDesktop({ accessToken: 'My Access Token' }).", - ); - } - const options: ClientOptions = { accessToken, ...opts, @@ -320,6 +314,9 @@ export class BaseBeeperDesktop { } protected async bearerAuth(opts: FinalRequestOptions): Promise { + if (this.accessToken == null) { + return undefined; + } return buildHeaders([{ Authorization: `Bearer ${this.accessToken}` }]); } From 7ed3d1adfac283d730ed88a3f0988d9468f0f550 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 May 2026 20:21:39 +0000 Subject: [PATCH 07/17] Update Desktop API Stainless config --- .stats.yml | 4 ++-- packages/mcp-server/src/http.ts | 41 +-------------------------------- 2 files changed, 3 insertions(+), 42 deletions(-) diff --git a/.stats.yml b/.stats.yml index c9bf663e..62239e78 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 72 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-81a39fdda33b337c5047b92f24bb2216150cba5507f9b66d3ef6a324e2b08e92.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-8ba2755730c4180ec88f92a300948445d7917898abfc912ca3fa6adc766a7520.yml openapi_spec_hash: 30b435d7585d8b6951610e7147369779 -config_hash: 6b409dea8089a8bfc72ed9919dc1d0bb +config_hash: a53888715ed00d433e5a5dafab9f7b9f diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 0817aa89..3c85a289 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -3,7 +3,6 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { ClientOptions } from '@beeper/desktop-api'; -import cors from 'cors'; import express from 'express'; import pino from 'pino'; import pinoHttp from 'pino-http'; @@ -12,11 +11,6 @@ import { getLogger } from './logger'; import { McpOptions } from './options'; import { initMcpServer, newMcpServer } from './server'; -const oauthResourceIdentifier = (req: express.Request): string => { - const protocol = req.headers['x-forwarded-proto'] ?? req.protocol; - return `${protocol}://${req.get('host')}/`; -}; - const newServer = async ({ clientOptions, mcpOptions, @@ -32,28 +26,7 @@ const newServer = async ({ const customInstructionsPath = mcpOptions.customInstructionsPath; const server = await newMcpServer({ stainlessApiKey, customInstructionsPath }); - // parseClientAuthHeaders throws if the Authorization header uses an unsupported - // scheme, or (when the second arg is true) if the header is missing entirely. - // On error, we return 401 with WWW-Authenticate pointing to the OAuth metadata - // endpoint so clients know how to authenticate (RFC 9728). - let authOptions: Partial; - try { - authOptions = parseClientAuthHeaders(req, true); - } catch (error) { - const resourceIdentifier = oauthResourceIdentifier(req); - res.set( - 'WWW-Authenticate', - `Bearer resource_metadata="${resourceIdentifier}.well-known/oauth-protected-resource"`, - ); - res.status(401).json({ - jsonrpc: '2.0', - error: { - code: -32000, - message: `Unauthorized: ${error instanceof Error ? error.message : error}`, - }, - }); - return null; - } + const authOptions = parseClientAuthHeaders(req, true); let upstreamClientEnvs: Record | undefined; const clientEnvsHeader = req.headers['x-stainless-mcp-client-envs']; @@ -152,16 +125,6 @@ const del = async (req: express.Request, res: express.Response) => { }); }; -const oauthMetadata = (req: express.Request, res: express.Response) => { - const resourceIdentifier = oauthResourceIdentifier(req); - res.json({ - resource: resourceIdentifier, - authorization_servers: ['http://localhost:23373'], - bearer_methods_supported: ['header'], - scopes_supported: 'read write', - }); -}; - const redactHeaders = (headers: Record) => { const hiddenHeaders = /auth|cookie|key|token|x-stainless-mcp-client-envs/i; const filtered = { ...headers }; @@ -231,8 +194,6 @@ export const streamableHTTPApp = ({ }), ); - app.get('/.well-known/oauth-protected-resource', cors(), oauthMetadata); - app.get('/health', async (req: express.Request, res: express.Response) => { res.status(200).send('OK'); }); From 19ef9d67b1e056b5bdfd518647a07831bc751205 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 16 May 2026 20:32:46 +0000 Subject: [PATCH 08/17] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 62239e78..8fcd9eab 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 72 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-8ba2755730c4180ec88f92a300948445d7917898abfc912ca3fa6adc766a7520.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-6cdaa898dcc095d108f684dd847bc19da7156b0a09ffb4cac2e613c53a0647e5.yml openapi_spec_hash: 30b435d7585d8b6951610e7147369779 -config_hash: a53888715ed00d433e5a5dafab9f7b9f +config_hash: 33cb47306fb0333ac538d5db65e8d52f From aed2b82485b34122ce88a0c5a30e8077b53240bd Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 17 May 2026 16:48:51 +0000 Subject: [PATCH 09/17] Update Desktop API docs and SDK config --- .stats.yml | 6 +- api.md | 234 +- packages/mcp-server/manifest.json | 2 +- packages/mcp-server/src/code-tool-worker.ts | 58 +- packages/mcp-server/src/local-docs-search.ts | 3132 +++++++++--------- packages/mcp-server/src/methods.ts | 348 +- src/client.ts | 63 +- src/tree-shakable.ts | 4 +- 8 files changed, 1925 insertions(+), 1922 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8fcd9eab..a6a4fc82 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 72 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-6cdaa898dcc095d108f684dd847bc19da7156b0a09ffb4cac2e613c53a0647e5.yml -openapi_spec_hash: 30b435d7585d8b6951610e7147369779 -config_hash: 33cb47306fb0333ac538d5db65e8d52f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-0427b028ffd00b4f8b75084116f801658d0279117b2d0e522d1f257c998f1fd0.yml +openapi_spec_hash: af3ed0745fca6831cf2540c36050d4e6 +config_hash: fbf60dd7c0de7e17c7e2bb0ee09e9937 diff --git a/api.md b/api.md index e93cdecc..f0c72a99 100644 --- a/api.md +++ b/api.md @@ -21,6 +21,123 @@ Types: - Reaction - User +# Accounts + +Types: + +- Account +- AccountListResponse + +Methods: + +- client.accounts.list() -> AccountListResponse + +## Contacts + +Types: + +- ContactSearchResponse + +Methods: + +- client.accounts.contacts.list(accountID, { ...params }) -> UsersCursorSearch +- client.accounts.contacts.search(accountID, { ...params }) -> ContactSearchResponse + +# Bridges + +Types: + +- BridgeAvailability +- BridgeListResponse + +Methods: + +- client.bridges.list() -> BridgeListResponse + +# Chats + +Types: + +- Chat +- ChatCreateResponse +- ChatListResponse +- ChatStartResponse + +Methods: + +- client.chats.create({ ...params }) -> ChatCreateResponse +- client.chats.retrieve(chatID, { ...params }) -> Chat +- client.chats.update(chatID, { ...params }) -> Chat +- client.chats.list({ ...params }) -> ChatListResponsesCursorNoLimit +- client.chats.archive(chatID, { ...params }) -> void +- client.chats.markRead(chatID, { ...params }) -> Chat +- client.chats.markUnread(chatID, { ...params }) -> Chat +- client.chats.notifyAnyway(chatID) -> Chat +- client.chats.search({ ...params }) -> ChatsCursorSearch +- client.chats.start({ ...params }) -> ChatStartResponse + +## Reminders + +Methods: + +- client.chats.reminders.create(chatID, { ...params }) -> void +- client.chats.reminders.delete(chatID) -> void + +## Messages + +### Reactions + +Types: + +- ReactionDeleteResponse +- ReactionAddResponse + +Methods: + +- client.chats.messages.reactions.delete(reactionKey, { ...params }) -> ReactionDeleteResponse +- client.chats.messages.reactions.add(messageID, { ...params }) -> ReactionAddResponse + +# Messages + +Types: + +- MessageUpdateResponse +- MessageSendResponse + +Methods: + +- client.messages.retrieve(messageID, { ...params }) -> Message +- client.messages.update(messageID, { ...params }) -> MessageUpdateResponse +- client.messages.list(chatID, { ...params }) -> MessagesCursorNoLimit +- client.messages.delete(messageID, { ...params }) -> void +- client.messages.search({ ...params }) -> MessagesCursorSearch +- client.messages.send(chatID, { ...params }) -> MessageSendResponse + +# Assets + +Types: + +- AssetDownloadResponse +- AssetUploadResponse +- AssetUploadBase64Response + +Methods: + +- client.assets.download({ ...params }) -> AssetDownloadResponse +- client.assets.serve({ ...params }) -> Response +- client.assets.upload({ ...params }) -> AssetUploadResponse +- client.assets.uploadBase64({ ...params }) -> AssetUploadBase64Response + +# Info + +Types: + +- InfoRetrieveResponse + +Methods: + +- client.info.retrieve() -> InfoRetrieveResponse + # App Types: @@ -117,39 +234,6 @@ Methods: - client.app.e2ee.verification.sas.confirm(verificationID) -> SaConfirmResponse - client.app.e2ee.verification.sas.start(verificationID) -> SaStartResponse -# Accounts - -Types: - -- Account -- AccountListResponse - -Methods: - -- client.accounts.list() -> AccountListResponse - -## Contacts - -Types: - -- ContactSearchResponse - -Methods: - -- client.accounts.contacts.list(accountID, { ...params }) -> UsersCursorSearch -- client.accounts.contacts.search(accountID, { ...params }) -> ContactSearchResponse - -# Bridges - -Types: - -- BridgeAvailability -- BridgeListResponse - -Methods: - -- client.bridges.list() -> BridgeListResponse - # Matrix ## Users @@ -291,87 +375,3 @@ Types: Methods: - client.matrix.bridges.capabilities.retrieve(bridgeID) -> CapabilityRetrieveResponse - -# Chats - -Types: - -- Chat -- ChatCreateResponse -- ChatListResponse -- ChatStartResponse - -Methods: - -- client.chats.create({ ...params }) -> ChatCreateResponse -- client.chats.retrieve(chatID, { ...params }) -> Chat -- client.chats.update(chatID, { ...params }) -> Chat -- client.chats.list({ ...params }) -> ChatListResponsesCursorNoLimit -- client.chats.archive(chatID, { ...params }) -> void -- client.chats.markRead(chatID, { ...params }) -> Chat -- client.chats.markUnread(chatID, { ...params }) -> Chat -- client.chats.notifyAnyway(chatID) -> Chat -- client.chats.search({ ...params }) -> ChatsCursorSearch -- client.chats.start({ ...params }) -> ChatStartResponse - -## Reminders - -Methods: - -- client.chats.reminders.create(chatID, { ...params }) -> void -- client.chats.reminders.delete(chatID) -> void - -## Messages - -### Reactions - -Types: - -- ReactionDeleteResponse -- ReactionAddResponse - -Methods: - -- client.chats.messages.reactions.delete(reactionKey, { ...params }) -> ReactionDeleteResponse -- client.chats.messages.reactions.add(messageID, { ...params }) -> ReactionAddResponse - -# Messages - -Types: - -- MessageUpdateResponse -- MessageSendResponse - -Methods: - -- client.messages.retrieve(messageID, { ...params }) -> Message -- client.messages.update(messageID, { ...params }) -> MessageUpdateResponse -- client.messages.list(chatID, { ...params }) -> MessagesCursorNoLimit -- client.messages.delete(messageID, { ...params }) -> void -- client.messages.search({ ...params }) -> MessagesCursorSearch -- client.messages.send(chatID, { ...params }) -> MessageSendResponse - -# Assets - -Types: - -- AssetDownloadResponse -- AssetUploadResponse -- AssetUploadBase64Response - -Methods: - -- client.assets.download({ ...params }) -> AssetDownloadResponse -- client.assets.serve({ ...params }) -> Response -- client.assets.upload({ ...params }) -> AssetUploadResponse -- client.assets.uploadBase64({ ...params }) -> AssetUploadBase64Response - -# Info - -Types: - -- InfoRetrieveResponse - -Methods: - -- client.info.retrieve() -> InfoRetrieveResponse diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index df87680b..07858738 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -30,7 +30,7 @@ "BEEPER_ACCESS_TOKEN": { "title": "access_token", "description": "Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations.", - "required": false, + "required": true, "type": "string" } }, diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index fbb4d67a..0a679b43 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -110,6 +110,35 @@ const fuse = new Fuse( [ 'client.focus', 'client.search', + 'client.accounts.list', + 'client.accounts.contacts.list', + 'client.accounts.contacts.search', + 'client.bridges.list', + 'client.chats.archive', + 'client.chats.create', + 'client.chats.list', + 'client.chats.markRead', + 'client.chats.markUnread', + 'client.chats.notifyAnyway', + 'client.chats.retrieve', + 'client.chats.search', + 'client.chats.start', + 'client.chats.update', + 'client.chats.reminders.create', + 'client.chats.reminders.delete', + 'client.chats.messages.reactions.add', + 'client.chats.messages.reactions.delete', + 'client.messages.delete', + 'client.messages.list', + 'client.messages.retrieve', + 'client.messages.search', + 'client.messages.send', + 'client.messages.update', + 'client.assets.download', + 'client.assets.serve', + 'client.assets.upload', + 'client.assets.uploadBase64', + 'client.info.retrieve', 'client.app.status', 'client.app.login.email', 'client.app.login.register', @@ -126,10 +155,6 @@ const fuse = new Fuse( 'client.app.e2ee.verification.qr.scan', 'client.app.e2ee.verification.sas.confirm', 'client.app.e2ee.verification.sas.start', - 'client.accounts.list', - 'client.accounts.contacts.list', - 'client.accounts.contacts.search', - 'client.bridges.list', 'client.matrix.users.retrieveProfile', 'client.matrix.users.accountData.retrieve', 'client.matrix.users.accountData.update', @@ -155,31 +180,6 @@ const fuse = new Fuse( 'client.matrix.bridges.rooms.createDm', 'client.matrix.bridges.rooms.createGroup', 'client.matrix.bridges.capabilities.retrieve', - 'client.chats.archive', - 'client.chats.create', - 'client.chats.list', - 'client.chats.markRead', - 'client.chats.markUnread', - 'client.chats.notifyAnyway', - 'client.chats.retrieve', - 'client.chats.search', - 'client.chats.start', - 'client.chats.update', - 'client.chats.reminders.create', - 'client.chats.reminders.delete', - 'client.chats.messages.reactions.add', - 'client.chats.messages.reactions.delete', - 'client.messages.delete', - 'client.messages.list', - 'client.messages.retrieve', - 'client.messages.search', - 'client.messages.send', - 'client.messages.update', - 'client.assets.download', - 'client.assets.serve', - 'client.assets.upload', - 'client.assets.uploadBase64', - 'client.info.retrieve', ], { threshold: 1, shouldSort: true }, ); diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 2282ce61..c287423d 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -145,3234 +145,3234 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, }, { - name: 'status', - endpoint: '/v1/app/status', + name: 'list', + endpoint: '/v1/accounts', httpMethod: 'get', - summary: 'Get app onboarding status', + summary: 'List Chat Accounts', description: - 'Return the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.', - stainlessPath: '(resource) app > (method) status', - qualified: 'client.app.status', + 'List Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.', + stainlessPath: '(resource) accounts > (method) list', + qualified: 'client.accounts.list', response: - "{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }", + "{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]", markdown: - "## status\n\n`client.app.status(): { e2ee: object; state: string; matrix?: object; verification?: object; }`\n\n**get** `/v1/app/status`\n\nReturn the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.\n\n### Returns\n\n- `{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n - `e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }`\n - `state: string`\n - `matrix?: { deviceID: string; homeserver: string; userID: string; }`\n - `verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.status();\n\nconsole.log(response);\n```", + "## list\n\n`client.accounts.list(): object[]`\n\n**get** `/v1/accounts`\n\nList Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.\n\n### Returns\n\n- `{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]`\n Accounts configured on this device. Includes accountID, bridge metadata, optional network name, and user identity.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);\n```", perLanguage: { typescript: { - method: 'client.app.status', + method: 'client.accounts.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.status();\n\nconsole.log(response.e2ee);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);", }, python: { - method: 'app.status', + method: 'accounts.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.status()\nprint(response.e2ee)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccounts = client.accounts.list()\nprint(accounts)', }, go: { - method: 'client.App.Status', + method: 'client.Accounts.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Status(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.E2ee)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccounts, err := client.Accounts.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accounts)\n}\n', }, cli: { - method: 'app status', - example: "beeper-desktop-cli app status \\\n --access-token 'My Access Token'", + method: 'accounts list', + example: "beeper-desktop-cli accounts list \\\n --access-token 'My Access Token'", }, php: { - method: 'app->status', + method: 'accounts->list', example: - "app->status();\n\nvar_dump($response);", + "accounts->list();\n\nvar_dump($accounts);", }, http: { example: - 'curl http://localhost:23373/v1/app/status \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/accounts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'start', - endpoint: '/v1/app/login/start', - httpMethod: 'post', - summary: 'Start app login', - description: 'Start a first-party Beeper Desktop sign-in session.', - stainlessPath: '(resource) app.login > (method) start', - qualified: 'client.app.login.start', - response: '{ request: string; type: string[]; }', + name: 'search', + endpoint: '/v1/accounts/{accountID}/contacts', + httpMethod: 'get', + summary: 'Search contacts', + description: + 'Search contacts on a specific account using merged account contacts, network search, and exact identifier lookup.', + stainlessPath: '(resource) accounts.contacts > (method) search', + qualified: 'client.accounts.contacts.search', + params: ['accountID: string;', 'query: string;'], + response: + '{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }', markdown: - "## start\n\n`client.app.login.start(): { request: string; type: string[]; }`\n\n**post** `/v1/app/login/start`\n\nStart a first-party Beeper Desktop sign-in session.\n\n### Returns\n\n- `{ request: string; type: string[]; }`\n\n - `request: string`\n - `type: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response);\n```", + "## search\n\n`client.accounts.contacts.search(accountID: string, query: string): { items: user[]; }`\n\n**get** `/v1/accounts/{accountID}/contacts`\n\nSearch contacts on a specific account using merged account contacts, network search, and exact identifier lookup.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `query: string`\n Text to search users by. Network-specific behavior.\n\n### Returns\n\n- `{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }`\n\n - `items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.app.login.start', + method: 'client.accounts.contacts.search', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response.request);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response.items);", }, python: { - method: 'app.login.start', + method: 'accounts.contacts.search', example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.start()\nprint(response.request)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.accounts.contacts.search(\n account_id="accountID",\n query="x",\n)\nprint(response.items)', }, go: { - method: 'client.App.Login.Start', + method: 'client.Accounts.Contacts.Search', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Start(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Request)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Accounts.Contacts.Search(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactSearchParams{\n\t\t\tQuery: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Items)\n}\n', }, cli: { - method: 'login start', - example: "beeper-desktop-cli app:login start \\\n --access-token 'My Access Token'", + method: 'contacts search', + example: + "beeper-desktop-cli accounts:contacts search \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --query x", }, php: { - method: 'app->login->start', + method: 'accounts->contacts->search', example: - "app->login->start();\n\nvar_dump($response);", + "accounts->contacts->search('accountID', query: 'x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/app/login/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID/contacts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'email', - endpoint: '/v1/app/login/email', - httpMethod: 'post', - summary: 'Send login code', - description: 'Send a sign-in code to the user email address.', - stainlessPath: '(resource) app.login > (method) email', - qualified: 'client.app.login.email', - params: ['email: string;', 'request: string;'], - response: 'object', + name: 'list', + endpoint: '/v1/accounts/{accountID}/contacts/list', + httpMethod: 'get', + summary: 'List contacts', + description: 'List merged contacts for a specific account with cursor-based pagination.', + stainlessPath: '(resource) accounts.contacts > (method) list', + qualified: 'client.accounts.contacts.list', + params: [ + 'accountID: string;', + 'cursor?: string;', + "direction?: 'after' | 'before';", + 'limit?: number;', + 'query?: string;', + ], + response: + '{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }', markdown: - "## email\n\n`client.app.login.email(email: string, request: string): object`\n\n**post** `/v1/app/login/email`\n\nSend a sign-in code to the user email address.\n\n### Parameters\n\n- `email: string`\n Email address to send the sign-in code to.\n\n- `request: string`\n Login request ID returned by the start step.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);\n```", + "## list\n\n`client.accounts.contacts.list(accountID: string, cursor?: string, direction?: 'after' | 'before', limit?: number, query?: string): { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n\n**get** `/v1/accounts/{accountID}/contacts/list`\n\nList merged contacts for a specific account with cursor-based pagination.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `limit?: number`\n Maximum contacts to return per page.\n\n- `query?: string`\n Optional search query for blended contact lookup.\n\n### Returns\n\n- `{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n User the account belongs to.\n\n - `id: string`\n - `cannotMessage?: boolean`\n - `email?: string`\n - `fullName?: string`\n - `imgURL?: string`\n - `isSelf?: boolean`\n - `phoneNumber?: string`\n - `username?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user);\n}\n```", perLanguage: { typescript: { - method: 'client.app.login.email', + method: 'client.accounts.contacts.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user.id);\n}", }, python: { - method: 'app.login.email', + method: 'accounts.contacts.list', example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.email(\n email="dev@stainless.com",\n request="request",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.accounts.contacts.list(\n account_id="accountID",\n)\npage = page.items[0]\nprint(page.id)', }, go: { - method: 'client.App.Login.Email', + method: 'client.Accounts.Contacts.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Email(context.TODO(), beeperdesktopapi.AppLoginEmailParams{\n\t\tEmail: "dev@stainless.com",\n\t\tRequest: "request",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Accounts.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'login email', + method: 'contacts list', example: - "beeper-desktop-cli app:login email \\\n --access-token 'My Access Token' \\\n --email dev@stainless.com \\\n --request request", + "beeper-desktop-cli accounts:contacts list \\\n --access-token 'My Access Token' \\\n --account-id accountID", }, php: { - method: 'app->login->email', + method: 'accounts->contacts->list', example: - "app->login->email(\n email: 'dev@stainless.com', request: 'request'\n);\n\nvar_dump($response);", + "accounts->contacts->list(\n 'accountID',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n limit: 1,\n query: 'x',\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/app/login/email \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "email": "dev@stainless.com",\n "request": "request"\n }\'', + 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID/contacts/list \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'response', - endpoint: '/v1/app/login/response', - httpMethod: 'post', - summary: 'Complete login with code', + name: 'list', + endpoint: '/v1/bridges', + httpMethod: 'get', + summary: 'List bridges', description: - 'Finish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.', - stainlessPath: '(resource) app.login > (method) response', - qualified: 'client.app.login.response', - params: ['request: string;', 'response: string;'], + 'List bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.', + stainlessPath: '(resource) bridges > (method) list', + qualified: 'client.bridges.list', response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }", + "{ items: { accounts: account[]; activeAccountCount: number; bridge: object; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]; }", markdown: - "## response\n\n`client.app.login.response(request: string, response: string): { appState: object; desktopAPI: object; matrix: object; } | { copy: object; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n**post** `/v1/app/login/response`\n\nFinish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.\n\n### Parameters\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `response: string`\n Sign-in code from the user email.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);\n```", + "## list\n\n`client.bridges.list(): { items: bridge_availability[]; }`\n\n**get** `/v1/bridges`\n\nList bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.\n\n### Returns\n\n- `{ items: { accounts: account[]; activeAccountCount: number; bridge: object; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]; }`\n Bridge-backed account types and their connected accounts.\n\n - `items: { accounts: { accountID: string; bridge: object; user: user; network?: string; }[]; activeAccountCount: number; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges);\n```", perLanguage: { typescript: { - method: 'client.app.login.response', + method: 'client.bridges.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges.items);", }, python: { - method: 'app.login.response', + method: 'bridges.list', example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.response(\n request="request",\n response="response",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nbridges = client.bridges.list()\nprint(bridges.items)', }, go: { - method: 'client.App.Login.Response', + method: 'client.Bridges.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Response(context.TODO(), beeperdesktopapi.AppLoginResponseParams{\n\t\tRequest: "request",\n\t\tResponse: "response",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tbridges, err := client.Bridges.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", bridges.Items)\n}\n', }, cli: { - method: 'login response', - example: - "beeper-desktop-cli app:login response \\\n --access-token 'My Access Token' \\\n --request request \\\n --response response", + method: 'bridges list', + example: "beeper-desktop-cli bridges list \\\n --access-token 'My Access Token'", }, php: { - method: 'app->login->response', + method: 'bridges->list', example: - "app->login->response(\n request: 'request', response: 'response'\n);\n\nvar_dump($response);", + "bridges->list();\n\nvar_dump($bridges);", }, http: { example: - 'curl http://localhost:23373/v1/app/login/response \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "request": "request",\n "response": "response"\n }\'', + 'curl http://localhost:23373/v1/bridges \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'register', - endpoint: '/v1/app/login/register', - httpMethod: 'post', - summary: 'Create account', - description: 'Create a Beeper account after the user chooses a username and accepts the Terms of Use.', - stainlessPath: '(resource) app.login > (method) register', - qualified: 'client.app.login.register', - params: ['acceptTerms: true;', 'leadToken: string;', 'request: string;', 'username: string;'], + name: 'retrieve', + endpoint: '/v1/chats/{chatID}', + httpMethod: 'get', + summary: 'Retrieve chat details', + description: 'Retrieve chat details including metadata, participants, and latest message', + stainlessPath: '(resource) chats > (method) retrieve', + qualified: 'client.chats.retrieve', + params: ['chatID: string;', 'maxParticipantCount?: number;'], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## register\n\n`client.app.login.register(acceptTerms: true, leadToken: string, request: string, username: string): { appState: object; desktopAPI: object; matrix: object; }`\n\n**post** `/v1/app/login/register`\n\nCreate a Beeper account after the user chooses a username and accepts the Terms of Use.\n\n### Parameters\n\n- `acceptTerms: true`\n Confirms that the user accepted the Terms of Use and acknowledged the Privacy Policy.\n\n- `leadToken: string`\n Registration token returned by Beeper.\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `username: string`\n Username selected by the user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }`\n - `matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response);\n```", + "## retrieve\n\n`client.chats.retrieve(chatID: string, maxParticipantCount?: number): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/{chatID}`\n\nRetrieve chat details including metadata, participants, and latest message\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `maxParticipantCount?: number`\n 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.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.login.register', + method: 'client.chats.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.login.register', + method: 'chats.retrieve', example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.register(\n accept_terms=True,\n lead_token="leadToken",\n request="request",\n username="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.retrieve(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.Login.Register', + method: 'client.Chats.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Register(context.TODO(), beeperdesktopapi.AppLoginRegisterParams{\n\t\tAcceptTerms: true,\n\t\tLeadToken: "leadToken",\n\t\tRequest: "request",\n\t\tUsername: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Get(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatGetParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'login register', + method: 'chats retrieve', example: - "beeper-desktop-cli app:login register \\\n --access-token 'My Access Token' \\\n --accept-terms true \\\n --lead-token leadToken \\\n --request request \\\n --username x", + "beeper-desktop-cli chats retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->login->register', + method: 'chats->retrieve', example: - "app->login->register(\n acceptTerms: true, leadToken: 'leadToken', request: 'request', username: 'x'\n);\n\nvar_dump($response);", + "chats->retrieve(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', maxParticipantCount: 100\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/login/register \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "acceptTerms": true,\n "leadToken": "leadToken",\n "request": "request",\n "username": "x"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'verify', - endpoint: '/v1/app/e2ee/recovery-code/verify', + name: 'create', + endpoint: '/v1/chats', httpMethod: 'post', - summary: 'Verify with recovery key', - description: 'Unlock encrypted messages with the user recovery key.', - stainlessPath: '(resource) app.e2ee.recovery_code > (method) verify', - qualified: 'client.app.e2ee.recoveryCode.verify', - params: ['recoveryCode: string;'], + summary: 'Create a chat', + description: 'Create a direct or group chat from participant IDs. Returns the created chat.', + stainlessPath: '(resource) chats > (method) create', + qualified: 'client.chats.create', + params: [ + 'accountID: string;', + 'participantIDs: string[];', + "type: 'single' | 'group';", + 'messageText?: string;', + 'title?: string;', + ], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## verify\n\n`client.app.e2ee.recoveryCode.verify(recoveryCode: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/verify`\n\nUnlock encrypted messages with the user recovery key.\n\n### Parameters\n\n- `recoveryCode: string`\n Recovery key saved by the user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' });\n\nconsole.log(response);\n```", + "## create\n\n`client.chats.create(accountID: string, participantIDs: string[], type: 'single' | 'group', messageText?: string, title?: string): object`\n\n**post** `/v1/chats`\n\nCreate a direct or group chat from participant IDs. Returns the created chat.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `participantIDs: string[]`\n User IDs to include in the new chat.\n\n- `type: 'single' | 'group'`\n 'single' requires exactly one participantID; 'group' supports multiple participants and optional title.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n- `title?: string`\n Optional title for group chats; ignored for single chats on most networks.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.create({\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n});\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.recoveryCode.verify', + method: 'client.chats.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' });\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.create({\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n});\n\nconsole.log(chat);", }, python: { - method: 'app.e2ee.recovery_code.verify', + method: 'chats.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.verify(\n recovery_code="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.create(\n account_id="accountID",\n participant_ids=["string"],\n type="single",\n)\nprint(chat)', }, go: { - method: 'client.App.E2ee.RecoveryCode.Verify', + method: 'client.Chats.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.Verify(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeVerifyParams{\n\t\tRecoveryCode: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.New(context.TODO(), beeperdesktopapi.ChatNewParams{\n\t\tAccountID: "accountID",\n\t\tParticipantIDs: []string{"string"},\n\t\tType: beeperdesktopapi.ChatNewParamsTypeSingle,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat)\n}\n', }, cli: { - method: 'recovery_code verify', + method: 'chats create', example: - "beeper-desktop-cli app:e2ee:recovery-code verify \\\n --access-token 'My Access Token' \\\n --recovery-code x", + "beeper-desktop-cli chats create \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --participant-id string \\\n --type single", }, php: { - method: 'app->e2ee->recoveryCode->verify', + method: 'chats->create', example: - "app->e2ee->recoveryCode->verify(recoveryCode: 'x');\n\nvar_dump($response);", + "chats->create(\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n messageText: 'messageText',\n title: 'title',\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/recovery-code/verify \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryCode": "x"\n }\'', + 'curl http://localhost:23373/v1/chats \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "accountID": "accountID",\n "participantIDs": [\n "string"\n ],\n "type": "single"\n }\'', }, }, }, { - name: 'mark_backed_up', - endpoint: '/v1/app/e2ee/recovery-code/mark-backed-up', + name: 'start', + endpoint: '/v1/chats/start', httpMethod: 'post', - summary: 'Mark recovery key as saved', - description: 'Record that the user saved their recovery key.', - stainlessPath: '(resource) app.e2ee.recovery_code > (method) mark_backed_up', - qualified: 'client.app.e2ee.recoveryCode.markBackedUp', + 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+.', + stainlessPath: '(resource) chats > (method) start', + qualified: 'client.chats.start', + params: [ + 'accountID: string;', + 'user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; };', + 'allowInvite?: boolean;', + 'messageText?: string;', + ], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## mark_backed_up\n\n`client.app.e2ee.recoveryCode.markBackedUp(): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/mark-backed-up`\n\nRecord that the user saved their recovery key.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.markBackedUp();\n\nconsole.log(response);\n```", + "## start\n\n`client.chats.start(accountID: string, user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }, allowInvite?: boolean, messageText?: string): object`\n\n**post** `/v1/chats/start`\n\nResolve 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+.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }`\n Merged user-like contact payload used to resolve the best identifier.\n - `id?: string`\n Known user ID when available.\n - `email?: string`\n Email candidate.\n - `fullName?: string`\n Display name hint used for ranking only.\n - `phoneNumber?: string`\n Phone number candidate (E.164 preferred).\n - `username?: string`\n Username/handle candidate.\n\n- `allowInvite?: boolean`\n Whether invite-based DM creation is allowed when required by the platform.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.recoveryCode.markBackedUp', + method: 'client.chats.start', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.markBackedUp();\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);", }, python: { - method: 'app.e2ee.recovery_code.mark_backed_up', + method: 'chats.start', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.mark_backed_up()\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.chats.start(\n account_id="accountID",\n user={},\n)\nprint(response)', }, go: { - method: 'client.App.E2ee.RecoveryCode.MarkBackedUp', + method: 'client.Chats.Start', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.MarkBackedUp(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Start(context.TODO(), beeperdesktopapi.ChatStartParams{\n\t\tAccountID: "accountID",\n\t\tUser: beeperdesktopapi.ChatStartParamsUser{},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'recovery_code mark_backed_up', + method: 'chats start', example: - "beeper-desktop-cli app:e2ee:recovery-code mark-backed-up \\\n --access-token 'My Access Token'", + "beeper-desktop-cli chats start \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --user '{}'", }, php: { - method: 'app->e2ee->recoveryCode->markBackedUp', + method: 'chats->start', example: - "app->e2ee->recoveryCode->markBackedUp();\n\nvar_dump($response);", + "chats->start(\n accountID: 'accountID',\n user: [\n 'id' => 'id',\n 'email' => 'email',\n 'fullName' => 'fullName',\n 'phoneNumber' => 'phoneNumber',\n 'username' => 'username',\n ],\n allowInvite: true,\n messageText: 'messageText',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/recovery-code/mark-backed-up \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/start \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "accountID": "accountID",\n "user": {}\n }\'', }, }, }, { - name: 'create', - endpoint: '/v1/app/e2ee/recovery-code/reset', - httpMethod: 'post', - summary: 'Create new recovery key', - description: 'Create a new recovery key when the user cannot use the existing one.', - stainlessPath: '(resource) app.e2ee.recovery_code.reset > (method) create', - qualified: 'client.app.e2ee.recoveryCode.reset.create', - params: ['recoveryCode?: string;'], + name: 'list', + endpoint: '/v1/chats', + httpMethod: 'get', + summary: 'List chats', + description: + 'List all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.', + stainlessPath: '(resource) chats > (method) list', + qualified: 'client.chats.list', + params: ['accountIDs?: string[];', 'cursor?: string;', "direction?: 'after' | 'before';"], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; recoveryCode: string; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## create\n\n`client.app.e2ee.recoveryCode.reset.create(recoveryCode?: string): { appState: object; recoveryCode: string; }`\n\n**post** `/v1/app/e2ee/recovery-code/reset`\n\nCreate a new recovery key when the user cannot use the existing one.\n\n### Parameters\n\n- `recoveryCode?: string`\n Existing recovery key, if the user has it.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; recoveryCode: string; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `recoveryCode: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reset = await client.app.e2ee.recoveryCode.reset.create();\n\nconsole.log(reset);\n```", + "## list\n\n`client.chats.list(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before'): object`\n\n**get** `/v1/chats`\n\nList all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit to specific account IDs. If omitted, fetches from all accounts.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n Chat with optional last message preview.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chatListResponse of client.chats.list()) {\n console.log(chatListResponse);\n}\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.recoveryCode.reset.create', + method: 'client.chats.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reset = await client.app.e2ee.recoveryCode.reset.create();\n\nconsole.log(reset.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const chatListResponse of client.chats.list()) {\n console.log(chatListResponse);\n}", }, python: { - method: 'app.e2ee.recovery_code.reset.create', + method: 'chats.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreset = client.app.e2ee.recovery_code.reset.create()\nprint(reset.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.chats.list()\npage = page.items[0]\nprint(page)', }, go: { - method: 'client.App.E2ee.RecoveryCode.Reset.New', + method: 'client.Chats.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treset, err := client.App.E2ee.RecoveryCode.Reset.New(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeResetNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reset.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.List(context.TODO(), beeperdesktopapi.ChatListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'reset create', - example: - "beeper-desktop-cli app:e2ee:recovery-code:reset create \\\n --access-token 'My Access Token'", + method: 'chats list', + example: "beeper-desktop-cli chats list \\\n --access-token 'My Access Token'", }, php: { - method: 'app->e2ee->recoveryCode->reset->create', + method: 'chats->list', example: - "app->e2ee->recoveryCode->reset->create(\n recoveryCode: 'recoveryCode'\n);\n\nvar_dump($reset);", + "chats->list(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/recovery-code/reset \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'confirm', - endpoint: '/v1/app/e2ee/recovery-code/reset/confirm', - httpMethod: 'post', - summary: 'Confirm new recovery key', - description: 'Confirm that the new recovery key should be used for this account.', - stainlessPath: '(resource) app.e2ee.recovery_code.reset > (method) confirm', - qualified: 'client.app.e2ee.recoveryCode.reset.confirm', - params: ['recoveryCode: string;'], + name: 'search', + endpoint: '/v1/chats/search', + httpMethod: 'get', + summary: 'Search chats', + description: 'Search chats by title, network, or participant names.', + stainlessPath: '(resource) chats > (method) search', + qualified: 'client.chats.search', + params: [ + 'accountIDs?: string[];', + 'cursor?: string;', + "direction?: 'after' | 'before';", + "inbox?: 'primary' | 'low-priority' | 'archive';", + 'includeMuted?: boolean;', + 'lastActivityAfter?: string;', + 'lastActivityBefore?: string;', + 'limit?: number;', + 'query?: string;', + "scope?: 'titles' | 'participants';", + "type?: 'single' | 'group' | 'any';", + 'unreadOnly?: boolean;', + ], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## confirm\n\n`client.app.e2ee.recoveryCode.reset.confirm(recoveryCode: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/reset/confirm`\n\nConfirm that the new recovery key should be used for this account.\n\n### Parameters\n\n- `recoveryCode: string`\n New recovery key returned by the reset step.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' });\n\nconsole.log(response);\n```", + "## search\n\n`client.chats.search(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before', inbox?: 'primary' | 'low-priority' | 'archive', includeMuted?: boolean, lastActivityAfter?: string, lastActivityBefore?: string, limit?: number, query?: string, scope?: 'titles' | 'participants', type?: 'single' | 'group' | 'any', unreadOnly?: boolean): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/search`\n\nSearch chats by title, network, or participant names.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Provide an array of account IDs to filter chats from specific messaging accounts only\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `inbox?: 'primary' | 'low-priority' | 'archive'`\n Filter by inbox type: \"primary\" (non-archived, non-low-priority), \"low-priority\", or \"archive\". If not specified, shows all chats.\n\n- `includeMuted?: boolean`\n 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.\n\n- `lastActivityAfter?: string`\n Provide an ISO datetime string to only retrieve chats with last activity after this time\n\n- `lastActivityBefore?: string`\n Provide an ISO datetime string to only retrieve chats with last activity before this time\n\n- `limit?: number`\n Set the maximum number of chats to retrieve. Valid range: 1-200, default is 50\n\n- `query?: string`\n Literal token search (non-semantic). Use single words users type (e.g., \"dinner\"). When multiple words provided, ALL must match. Case-insensitive.\n\n- `scope?: 'titles' | 'participants'`\n Search scope: 'titles' matches title + network; 'participants' matches participant names.\n\n- `type?: 'single' | 'group' | 'any'`\n Specify the type of chats to retrieve: use \"single\" for direct messages, \"group\" for group chats, or \"any\" to get all types\n\n- `unreadOnly?: boolean`\n Set to true to only retrieve chats that have unread messages\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat);\n}\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.recoveryCode.reset.confirm', + method: 'client.chats.search', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' });\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat.id);\n}", }, python: { - method: 'app.e2ee.recovery_code.reset.confirm', + method: 'chats.search', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.reset.confirm(\n recovery_code="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.chats.search()\npage = page.items[0]\nprint(page.id)', }, go: { - method: 'client.App.E2ee.RecoveryCode.Reset.Confirm', + method: 'client.Chats.Search', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.Reset.Confirm(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeResetConfirmParams{\n\t\tRecoveryCode: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.Search(context.TODO(), beeperdesktopapi.ChatSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'reset confirm', - example: - "beeper-desktop-cli app:e2ee:recovery-code:reset confirm \\\n --access-token 'My Access Token' \\\n --recovery-code x", + method: 'chats search', + example: "beeper-desktop-cli chats search \\\n --access-token 'My Access Token'", }, php: { - method: 'app->e2ee->recoveryCode->reset->confirm', + method: 'chats->search', example: - "app->e2ee->recoveryCode->reset->confirm(recoveryCode: 'x');\n\nvar_dump($response);", + "chats->search(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n inbox: 'primary',\n includeMuted: true,\n lastActivityAfter: new \\DateTimeImmutable('2019-12-27T18:11:19.117Z'),\n lastActivityBefore: new \\DateTimeImmutable('2019-12-27T18:11:19.117Z'),\n limit: 1,\n query: 'x',\n scope: 'titles',\n type: 'single',\n unreadOnly: true,\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/recovery-code/reset/confirm \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryCode": "x"\n }\'', + 'curl http://localhost:23373/v1/chats/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'create', - endpoint: '/v1/app/e2ee/verification', + name: 'archive', + endpoint: '/v1/chats/{chatID}/archive', httpMethod: 'post', - summary: 'Start device verification', - description: 'Start verifying this device from another signed-in device.', - stainlessPath: '(resource) app.e2ee.verification > (method) create', - qualified: 'client.app.e2ee.verification.create', - params: ['userID?: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; verificationID: string; }", + 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', + stainlessPath: '(resource) chats > (method) archive', + qualified: 'client.chats.archive', + params: ['chatID: string;', 'archived?: boolean;'], markdown: - "## create\n\n`client.app.e2ee.verification.create(userID?: string): { appState: object; verificationID: string; }`\n\n**post** `/v1/app/e2ee/verification`\n\nStart verifying this device from another signed-in device.\n\n### Parameters\n\n- `userID?: string`\n User ID to verify. Defaults to the signed-in user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; verificationID: string; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `verificationID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.e2ee.verification.create();\n\nconsole.log(verification);\n```", + "## archive\n\n`client.chats.archive(chatID: string, archived?: boolean): void`\n\n**post** `/v1/chats/{chatID}/archive`\n\nArchive or unarchive a chat. Set archived=true to move to archive, archived=false to move back to inbox\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `archived?: boolean`\n True to archive, false to unarchive\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.create', + method: 'client.chats.archive', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.e2ee.verification.create();\n\nconsole.log(verification.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com');", }, python: { - method: 'app.e2ee.verification.create', + method: 'chats.archive', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.e2ee.verification.create()\nprint(verification.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.archive(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', }, go: { - method: 'client.App.E2ee.Verification.New', + method: 'client.Chats.Archive', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.E2ee.Verification.New(context.TODO(), beeperdesktopapi.AppE2eeVerificationNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Archive(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatArchiveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, cli: { - method: 'verification create', - example: "beeper-desktop-cli app:e2ee:verification create \\\n --access-token 'My Access Token'", + method: 'chats archive', + example: + "beeper-desktop-cli chats archive \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->create', + method: 'chats->archive', example: - "app->e2ee->verification->create(userID: 'userID');\n\nvar_dump($verification);", + "chats->archive(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', archived: true\n);\n\nvar_dump($result);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/archive \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'accept', - endpoint: '/v1/app/e2ee/verification/{verificationID}/accept', - httpMethod: 'post', - summary: 'Accept device verification', - description: 'Accept an incoming device verification request.', - stainlessPath: '(resource) app.e2ee.verification > (method) accept', - qualified: 'client.app.e2ee.verification.accept', - params: ['verificationID: string;'], + name: 'update', + endpoint: '/v1/chats/{chatID}', + httpMethod: '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.', + stainlessPath: '(resource) chats > (method) update', + qualified: 'client.chats.update', + params: [ + 'chatID: string;', + 'description?: string;', + 'draft?: { text: string; attachments?: object; };', + 'imgURL?: string;', + 'isArchived?: boolean;', + 'isLowPriority?: boolean;', + 'isMuted?: boolean;', + 'isPinned?: boolean;', + 'messageExpirySeconds?: number;', + 'title?: string;', + ], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## accept\n\n`client.app.e2ee.verification.accept(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/accept`\n\nAccept an incoming device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.accept('x');\n\nconsole.log(response);\n```", + "## update\n\n`client.chats.update(chatID: string, description?: string, draft?: { text: string; attachments?: object; }, imgURL?: string, isArchived?: boolean, isLowPriority?: boolean, isMuted?: boolean, isPinned?: boolean, messageExpirySeconds?: number, title?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**patch** `/v1/chats/{chatID}`\n\nUpdate 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.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `description?: string`\n Group chat description/topic. Support depends on the chat account and chat permissions.\n\n- `draft?: { text: string; attachments?: object; }`\n Draft object to set or clear. Non-empty drafts are only accepted when the current draft is empty. Send draft=null to clear text and attachments together before setting a new draft.\n - `text: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n - `attachments?: object`\n Draft attachments keyed by attachment ID. Each attachment must reference an uploadID returned by the upload file endpoint.\n\n- `imgURL?: string`\n Local filesystem path to a group chat avatar image. Support depends on the chat account and chat permissions.\n\n- `isArchived?: boolean`\n Archive or unarchive the chat.\n\n- `isLowPriority?: boolean`\n Mark or unmark the chat as low priority when supported by the account.\n\n- `isMuted?: boolean`\n Mute or unmute the chat.\n\n- `isPinned?: boolean`\n Pin or unpin the chat when supported by the account.\n\n- `messageExpirySeconds?: number`\n Disappearing-message timer in seconds, or null to clear when supported.\n\n- `title?: string`\n Custom chat title. Support depends on the chat account and chat permissions.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.accept', + method: 'client.chats.update', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.accept('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.e2ee.verification.accept', + method: 'chats.update', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.accept(\n "x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.update(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.E2ee.Verification.Accept', + method: 'client.Chats.Update', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Accept(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Update(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'verification accept', + method: 'chats update', example: - "beeper-desktop-cli app:e2ee:verification accept \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop-cli chats update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->accept', + method: 'chats->update', example: - "app->e2ee->verification->accept('x');\n\nvar_dump($response);", + "chats->update(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n description: 'description',\n draft: [\n 'text' => 'text',\n 'attachments' => [\n 'foo' => [\n 'uploadID' => 'uploadID',\n 'id' => 'id',\n 'duration' => 0,\n 'fileName' => 'fileName',\n 'mimeType' => 'mimeType',\n 'size' => ['height' => 0, 'width' => 0],\n 'type' => 'image',\n ],\n ],\n ],\n imgURL: 'imgURL',\n isArchived: true,\n isLowPriority: true,\n isMuted: true,\n isPinned: true,\n messageExpirySeconds: 0,\n title: 'title',\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/accept \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID \\\n -X PATCH \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'cancel', - endpoint: '/v1/app/e2ee/verification/{verificationID}/cancel', + name: 'mark_read', + endpoint: '/v1/chats/{chatID}/read', httpMethod: 'post', - summary: 'Cancel device verification', - description: 'Cancel an active device verification request.', - stainlessPath: '(resource) app.e2ee.verification > (method) cancel', - qualified: 'client.app.e2ee.verification.cancel', - params: ['verificationID: string;', 'code?: string;', 'reason?: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + summary: 'Mark a chat as read', + description: 'Mark a chat as read, optionally through a specific message ID.', + stainlessPath: '(resource) chats > (method) mark_read', + qualified: 'client.chats.markRead', + params: ['chatID: string;', 'messageID?: string;'], + response: + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## cancel\n\n`client.app.e2ee.verification.cancel(verificationID: string, code?: string, reason?: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/cancel`\n\nCancel an active device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n- `code?: string`\n Optional cancellation code.\n\n- `reason?: string`\n Optional user-facing cancellation reason.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.cancel('x');\n\nconsole.log(response);\n```", + "## mark_read\n\n`client.chats.markRead(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/read`\n\nMark a chat as read, optionally through a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark read through.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.cancel', + method: 'client.chats.markRead', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.cancel('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.e2ee.verification.cancel', + method: 'chats.mark_read', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.cancel(\n verification_id="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.mark_read(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.E2ee.Verification.Cancel', + method: 'client.Chats.MarkRead', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Cancel(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.AppE2eeVerificationCancelParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkRead(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkReadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'verification cancel', + method: 'chats mark_read', example: - "beeper-desktop-cli app:e2ee:verification cancel \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop-cli chats mark-read \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->cancel', + method: 'chats->markRead', example: - "app->e2ee->verification->cancel(\n 'x', code: 'code', reason: 'reason'\n);\n\nvar_dump($response);", + "chats->markRead(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/cancel \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/read \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'scan', - endpoint: '/v1/app/e2ee/verification/qr/scan', + name: 'mark_unread', + endpoint: '/v1/chats/{chatID}/unread', httpMethod: 'post', - summary: 'Scan verification QR code', - description: 'Submit the QR code scanned from another signed-in device.', - stainlessPath: '(resource) app.e2ee.verification.qr > (method) scan', - qualified: 'client.app.e2ee.verification.qr.scan', - params: ['data: string;'], + summary: 'Mark a chat as unread', + description: 'Mark a chat as unread, optionally from a specific message ID.', + stainlessPath: '(resource) chats > (method) mark_unread', + qualified: 'client.chats.markUnread', + params: ['chatID: string;', 'messageID?: string;'], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## scan\n\n`client.app.e2ee.verification.qr.scan(data: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/qr/scan`\n\nSubmit the QR code scanned from another signed-in device.\n\n### Parameters\n\n- `data: string`\n QR code payload scanned from the other device.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.qr.scan({ data: 'x' });\n\nconsole.log(response);\n```", + "## mark_unread\n\n`client.chats.markUnread(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/unread`\n\nMark a chat as unread, optionally from a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark unread from.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.qr.scan', + method: 'client.chats.markUnread', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.qr.scan({ data: 'x' });\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.e2ee.verification.qr.scan', + method: 'chats.mark_unread', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.qr.scan(\n data="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.mark_unread(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.E2ee.Verification.Qr.Scan', + method: 'client.Chats.MarkUnread', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Qr.Scan(context.TODO(), beeperdesktopapi.AppE2eeVerificationQrScanParams{\n\t\tData: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkUnread(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkUnreadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'qr scan', + method: 'chats mark_unread', example: - "beeper-desktop-cli app:e2ee:verification:qr scan \\\n --access-token 'My Access Token' \\\n --data x", + "beeper-desktop-cli chats mark-unread \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->qr->scan', + method: 'chats->markUnread', example: - "app->e2ee->verification->qr->scan(data: 'x');\n\nvar_dump($response);", + "chats->markUnread(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/qr/scan \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "data": "x"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/unread \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'confirm_scanned', - endpoint: '/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned', + name: 'notify_anyway', + endpoint: '/v1/chats/{chatID}/notify-anyway', httpMethod: 'post', - summary: 'Confirm QR code scan', - description: 'Confirm that another device scanned this device QR code.', - stainlessPath: '(resource) app.e2ee.verification.qr > (method) confirm_scanned', - qualified: 'client.app.e2ee.verification.qr.confirmScanned', - params: ['verificationID: string;'], + 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.', + stainlessPath: '(resource) chats > (method) notify_anyway', + qualified: 'client.chats.notifyAnyway', + params: ['chatID: string;'], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## confirm_scanned\n\n`client.app.e2ee.verification.qr.confirmScanned(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned`\n\nConfirm that another device scanned this device QR code.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.qr.confirmScanned('x');\n\nconsole.log(response);\n```", + "## notify_anyway\n\n`client.chats.notifyAnyway(chatID: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/notify-anyway`\n\nForce a delivery notification when supported by the underlying network. Currently intended for iMessage on macOS; unsupported networks return an error.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.qr.confirmScanned', + method: 'client.chats.notifyAnyway', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.qr.confirmScanned('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.e2ee.verification.qr.confirm_scanned', + method: 'chats.notify_anyway', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.qr.confirm_scanned(\n "x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.notify_anyway(\n "!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.E2ee.Verification.Qr.ConfirmScanned', + method: 'client.Chats.NotifyAnyway', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Qr.ConfirmScanned(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.NotifyAnyway(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatNotifyAnywayParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'qr confirm_scanned', + method: 'chats notify_anyway', example: - "beeper-desktop-cli app:e2ee:verification:qr confirm-scanned \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop-cli chats notify-anyway \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->qr->confirmScanned', + method: 'chats->notifyAnyway', example: - "app->e2ee->verification->qr->confirmScanned('x');\n\nvar_dump($response);", + "chats->notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/qr/confirm-scanned \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/notify-anyway \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'start', - endpoint: '/v1/app/e2ee/verification/{verificationID}/sas/start', + name: 'create', + endpoint: '/v1/chats/{chatID}/reminders', httpMethod: 'post', - summary: 'Start emoji verification', - description: 'Start emoji comparison for device verification.', - stainlessPath: '(resource) app.e2ee.verification.sas > (method) start', - qualified: 'client.app.e2ee.verification.sas.start', - params: ['verificationID: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + summary: 'Create a chat reminder', + description: 'Set a reminder for a chat at a specific time', + stainlessPath: '(resource) chats.reminders > (method) create', + qualified: 'client.chats.reminders.create', + params: ['chatID: string;', 'reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; };'], markdown: - "## start\n\n`client.app.e2ee.verification.sas.start(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/sas/start`\n\nStart emoji comparison for device verification.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.sas.start('x');\n\nconsole.log(response);\n```", + "## create\n\n`client.chats.reminders.create(chatID: string, reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }): void`\n\n**post** `/v1/chats/{chatID}/reminders`\n\nSet a reminder for a chat at a specific time\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }`\n Reminder configuration\n - `remindAt: string`\n Timestamp when the reminder should trigger.\n - `dismissOnIncomingMessage?: boolean`\n Cancel reminder if someone messages in the chat\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', { reminder: { remindAt: '2025-08-31T23:30:12.520Z' } })\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.sas.start', + method: 'client.chats.reminders.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.sas.start('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', {\n reminder: { remindAt: '2025-08-31T23:30:12.520Z' },\n});", }, python: { - method: 'app.e2ee.verification.sas.start', + method: 'chats.reminders.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.sas.start(\n "x",\n)\nprint(response.app_state)', + 'import os\nfrom datetime import datetime\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.reminders.create(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n reminder={\n "remind_at": datetime.fromisoformat("2025-08-31T23:30:12.520")\n },\n)', }, go: { - method: 'client.App.E2ee.Verification.Sas.Start', + method: 'client.Chats.Reminders.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Sas.Start(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"time"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.New(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatReminderNewParams{\n\t\t\tReminder: beeperdesktopapi.ChatReminderNewParamsReminder{\n\t\t\t\tRemindAt: time.Now(),\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, cli: { - method: 'sas start', + method: 'reminders create', example: - "beeper-desktop-cli app:e2ee:verification:sas start \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop-cli chats:reminders create \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --reminder \"{remindAt: '2025-08-31T23:30:12.520Z'}\"", }, php: { - method: 'app->e2ee->verification->sas->start', + method: 'chats->reminders->create', example: - "app->e2ee->verification->sas->start('x');\n\nvar_dump($response);", + "chats->reminders->create(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reminder: [\n 'remindAt' => new \\DateTimeImmutable('2025-08-31T23:30:12.520Z'),\n 'dismissOnIncomingMessage' => true,\n ],\n);\n\nvar_dump($result);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/sas/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/reminders \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reminder": {\n "remindAt": "2025-08-31T23:30:12.520Z"\n }\n }\'', }, }, }, { - name: 'confirm', - endpoint: '/v1/app/e2ee/verification/{verificationID}/sas/confirm', - httpMethod: 'post', - summary: 'Confirm emoji verification', - description: 'Confirm that the emoji or number sequence matches on both devices.', - stainlessPath: '(resource) app.e2ee.verification.sas > (method) confirm', - qualified: 'client.app.e2ee.verification.sas.confirm', - params: ['verificationID: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + name: 'delete', + endpoint: '/v1/chats/{chatID}/reminders', + httpMethod: 'delete', + summary: 'Delete a chat reminder', + description: 'Clear an existing reminder from a chat', + stainlessPath: '(resource) chats.reminders > (method) delete', + qualified: 'client.chats.reminders.delete', + params: ['chatID: string;'], markdown: - "## confirm\n\n`client.app.e2ee.verification.sas.confirm(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/sas/confirm`\n\nConfirm that the emoji or number sequence matches on both devices.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.sas.confirm('x');\n\nconsole.log(response);\n```", + "## delete\n\n`client.chats.reminders.delete(chatID: string): void`\n\n**delete** `/v1/chats/{chatID}/reminders`\n\nClear an existing reminder from a chat\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.sas.confirm', + method: 'client.chats.reminders.delete', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.sas.confirm('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com');", }, python: { - method: 'app.e2ee.verification.sas.confirm', + method: 'chats.reminders.delete', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.sas.confirm(\n "x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.reminders.delete(\n "!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', }, go: { - method: 'client.App.E2ee.Verification.Sas.Confirm', + method: 'client.Chats.Reminders.Delete', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Sas.Confirm(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.Delete(context.TODO(), "!NCdzlIaMjZUmvmvyHU:beeper.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, cli: { - method: 'sas confirm', + method: 'reminders delete', example: - "beeper-desktop-cli app:e2ee:verification:sas confirm \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop-cli chats:reminders delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->sas->confirm', + method: 'chats->reminders->delete', example: - "app->e2ee->verification->sas->confirm('x');\n\nvar_dump($response);", + "chats->reminders->delete('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nvar_dump($result);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/sas/confirm \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/reminders \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'list', - endpoint: '/v1/accounts', - httpMethod: 'get', - summary: 'List Chat Accounts', - description: - 'List Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.', - stainlessPath: '(resource) accounts > (method) list', - qualified: 'client.accounts.list', + name: 'add', + endpoint: '/v1/chats/{chatID}/messages/{messageID}/reactions', + httpMethod: 'post', + summary: 'Add a reaction', + description: 'Add a reaction to an existing message.', + stainlessPath: '(resource) chats.messages.reactions > (method) add', + qualified: 'client.chats.messages.reactions.add', + params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;', 'transactionID?: string;'], response: - "{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]", + '{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }', markdown: - "## list\n\n`client.accounts.list(): object[]`\n\n**get** `/v1/accounts`\n\nList Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.\n\n### Returns\n\n- `{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]`\n Accounts configured on this device. Includes accountID, bridge metadata, optional network name, and user identity.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);\n```", + "## add\n\n`client.chats.messages.reactions.add(chatID: string, messageID: string, reactionKey: string, transactionID?: string): { chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n**post** `/v1/chats/{chatID}/messages/{messageID}/reactions`\n\nAdd a reaction to an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to add (emoji, shortcode, or custom emoji key)\n\n- `transactionID?: string`\n Optional transaction ID for deduplication and send tracking\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n - `transactionID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.messages.reactions.add('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', reactionKey: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.accounts.list', + method: 'client.chats.messages.reactions.add', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.chats.messages.reactions.add('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reactionKey: 'x',\n});\n\nconsole.log(response.chatID);", }, python: { - method: 'accounts.list', + method: 'chats.messages.reactions.add', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccounts = client.accounts.list()\nprint(accounts)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.chats.messages.reactions.add(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n reaction_key="x",\n)\nprint(response.chat_id)', }, go: { - method: 'client.Accounts.List', + method: 'client.Chats.Messages.Reactions.Add', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccounts, err := client.Accounts.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accounts)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Messages.Reactions.Add(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.ChatMessageReactionAddParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tReactionKey: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ChatID)\n}\n', }, cli: { - method: 'accounts list', - example: "beeper-desktop-cli accounts list \\\n --access-token 'My Access Token'", + method: 'reactions add', + example: + "beeper-desktop-cli chats:messages:reactions add \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", }, php: { - method: 'accounts->list', + method: 'chats->messages->reactions->add', example: - "accounts->list();\n\nvar_dump($accounts);", + "chats->messages->reactions->add(\n '1343993',\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reactionKey: 'x',\n transactionID: 'transactionID',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/accounts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID/reactions \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reactionKey": "x"\n }\'', }, }, }, { - name: 'search', - endpoint: '/v1/accounts/{accountID}/contacts', - httpMethod: 'get', - summary: 'Search contacts', - description: - 'Search contacts on a specific account using merged account contacts, network search, and exact identifier lookup.', - stainlessPath: '(resource) accounts.contacts > (method) search', - qualified: 'client.accounts.contacts.search', - params: ['accountID: string;', 'query: string;'], - response: - '{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }', - markdown: - "## search\n\n`client.accounts.contacts.search(accountID: string, query: string): { items: user[]; }`\n\n**get** `/v1/accounts/{accountID}/contacts`\n\nSearch contacts on a specific account using merged account contacts, network search, and exact identifier lookup.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `query: string`\n Text to search users by. Network-specific behavior.\n\n### Returns\n\n- `{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }`\n\n - `items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.accounts.contacts.search', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response.items);", + name: 'delete', + endpoint: '/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}', + httpMethod: 'delete', + summary: 'Remove a reaction', + description: 'Remove the reaction added by the authenticated user from an existing message.', + stainlessPath: '(resource) chats.messages.reactions > (method) delete', + qualified: 'client.chats.messages.reactions.delete', + params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;'], + response: '{ chatID: string; messageID: string; reactionKey: string; success: true; }', + markdown: + "## delete\n\n`client.chats.messages.reactions.delete(chatID: string, messageID: string, reactionKey: string): { chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}`\n\nRemove the reaction added by the authenticated user from an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to remove (emoji, shortcode, or custom emoji key)\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reaction = await client.chats.messages.reactions.delete('x', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993' });\n\nconsole.log(reaction);\n```", + perLanguage: { + typescript: { + method: 'client.chats.messages.reactions.delete', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reaction = await client.chats.messages.reactions.delete('x', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n messageID: '1343993',\n});\n\nconsole.log(reaction.chatID);", }, python: { - method: 'accounts.contacts.search', + method: 'chats.messages.reactions.delete', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.accounts.contacts.search(\n account_id="accountID",\n query="x",\n)\nprint(response.items)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreaction = client.chats.messages.reactions.delete(\n reaction_key="x",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n message_id="1343993",\n)\nprint(reaction.chat_id)', }, go: { - method: 'client.Accounts.Contacts.Search', + method: 'client.Chats.Messages.Reactions.Delete', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Accounts.Contacts.Search(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactSearchParams{\n\t\t\tQuery: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Items)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treaction, err := client.Chats.Messages.Reactions.Delete(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.ChatMessageReactionDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tMessageID: "1343993",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reaction.ChatID)\n}\n', }, cli: { - method: 'contacts search', + method: 'reactions delete', example: - "beeper-desktop-cli accounts:contacts search \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --query x", + "beeper-desktop-cli chats:messages:reactions delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", }, php: { - method: 'accounts->contacts->search', + method: 'chats->messages->reactions->delete', example: - "accounts->contacts->search('accountID', query: 'x');\n\nvar_dump($response);", + "chats->messages->reactions->delete(\n 'x', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($reaction);", }, http: { example: - 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID/contacts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID/reactions/$REACTION_KEY \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'list', - endpoint: '/v1/accounts/{accountID}/contacts/list', + name: 'search', + endpoint: '/v1/messages/search', httpMethod: 'get', - summary: 'List contacts', - description: 'List merged contacts for a specific account with cursor-based pagination.', - stainlessPath: '(resource) accounts.contacts > (method) list', - qualified: 'client.accounts.contacts.list', + summary: 'Search messages', + description: 'Search messages across chats.', + stainlessPath: '(resource) messages > (method) search', + qualified: 'client.messages.search', params: [ - 'accountID: string;', + 'accountIDs?: string[];', + 'chatIDs?: string[];', + "chatType?: 'group' | 'single';", 'cursor?: string;', + 'dateAfter?: string;', + 'dateBefore?: string;', "direction?: 'after' | 'before';", + 'excludeLowPriority?: boolean;', + 'includeMuted?: boolean;', 'limit?: number;', + "mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[];", 'query?: string;', + 'sender?: string;', ], response: - '{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }', + "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## list\n\n`client.accounts.contacts.list(accountID: string, cursor?: string, direction?: 'after' | 'before', limit?: number, query?: string): { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n\n**get** `/v1/accounts/{accountID}/contacts/list`\n\nList merged contacts for a specific account with cursor-based pagination.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `limit?: number`\n Maximum contacts to return per page.\n\n- `query?: string`\n Optional search query for blended contact lookup.\n\n### Returns\n\n- `{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n User the account belongs to.\n\n - `id: string`\n - `cannotMessage?: boolean`\n - `email?: string`\n - `fullName?: string`\n - `imgURL?: string`\n - `isSelf?: boolean`\n - `phoneNumber?: string`\n - `username?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user);\n}\n```", + "## search\n\n`client.messages.search(accountIDs?: string[], chatIDs?: string[], chatType?: 'group' | 'single', cursor?: string, dateAfter?: string, dateBefore?: string, direction?: 'after' | 'before', excludeLowPriority?: boolean, includeMuted?: boolean, limit?: number, mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[], query?: string, sender?: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/messages/search`\n\nSearch messages across chats.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit search to specific account IDs.\n\n- `chatIDs?: string[]`\n Limit search to specific chat IDs.\n\n- `chatType?: 'group' | 'single'`\n Filter by chat type: 'group' for group chats, 'single' for 1:1 chats.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `dateAfter?: string`\n Only include messages with timestamp strictly after this ISO 8601 datetime (e.g., '2024-07-01T00:00:00Z' or '2024-07-01T00:00:00+02:00').\n\n- `dateBefore?: string`\n Only include messages with timestamp strictly before this ISO 8601 datetime (e.g., '2024-07-31T23:59:59Z' or '2024-07-31T23:59:59+02:00').\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `excludeLowPriority?: boolean`\n Exclude messages marked Low Priority by the user. Default: true. Set to false to include all.\n\n- `includeMuted?: boolean`\n Include messages in 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.\n\n- `limit?: number`\n Maximum number of messages to return.\n\n- `mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[]`\n Filter messages by media types. Use ['any'] for any media type, or specify exact types like ['video', 'image']. Omit for no media filtering.\n\n- `query?: string`\n Literal word search (non-semantic). Finds messages containing these EXACT words in any order. Use single words users actually type, not concepts or phrases. Example: use \"dinner\" not \"dinner plans\", use \"sick\" not \"health issues\". If omitted, returns results filtered only by other parameters.\n\n- `sender?: string`\n Filter by sender: 'me' (messages sent by the authenticated user), 'others' (messages sent by others), or a specific user ID string (user.id).\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message);\n}\n```", perLanguage: { typescript: { - method: 'client.accounts.contacts.list', + method: 'client.messages.search', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user.id);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message.id);\n}", }, python: { - method: 'accounts.contacts.list', + method: 'messages.search', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.accounts.contacts.list(\n account_id="accountID",\n)\npage = page.items[0]\nprint(page.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.messages.search()\npage = page.items[0]\nprint(page.id)', }, go: { - method: 'client.Accounts.Contacts.List', + method: 'client.Messages.Search', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Accounts.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"accountID",\n\t\tbeeperdesktopapi.AccountContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.Search(context.TODO(), beeperdesktopapi.MessageSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'contacts list', - example: - "beeper-desktop-cli accounts:contacts list \\\n --access-token 'My Access Token' \\\n --account-id accountID", + method: 'messages search', + example: "beeper-desktop-cli messages search \\\n --access-token 'My Access Token'", }, php: { - method: 'accounts->contacts->list', + method: 'messages->search', example: - "accounts->contacts->list(\n 'accountID',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n limit: 1,\n query: 'x',\n);\n\nvar_dump($page);", + "messages->search(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n chatIDs: ['!NCdzlIaMjZUmvmvyHU:beeper.com', '1231073'],\n chatType: 'group',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n dateAfter: new \\DateTimeImmutable('2025-08-01T00:00:00Z'),\n dateBefore: new \\DateTimeImmutable('2025-08-31T23:59:59Z'),\n direction: 'before',\n excludeLowPriority: true,\n includeMuted: true,\n limit: 20,\n mediaTypes: ['any'],\n query: 'dinner',\n sender: 'sender',\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID/contacts/list \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/messages/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { name: 'list', - endpoint: '/v1/bridges', + endpoint: '/v1/chats/{chatID}/messages', httpMethod: 'get', - summary: 'List bridges', - description: - 'List bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.', - stainlessPath: '(resource) bridges > (method) list', - qualified: 'client.bridges.list', + summary: 'List messages', + description: 'List all messages in a chat with cursor-based pagination. Sorted by timestamp.', + stainlessPath: '(resource) messages > (method) list', + qualified: 'client.messages.list', + params: ['chatID: string;', 'cursor?: string;', "direction?: 'after' | 'before';"], response: - "{ items: { accounts: account[]; activeAccountCount: number; bridge: object; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]; }", + "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## list\n\n`client.bridges.list(): { items: bridge_availability[]; }`\n\n**get** `/v1/bridges`\n\nList bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.\n\n### Returns\n\n- `{ items: { accounts: account[]; activeAccountCount: number; bridge: object; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]; }`\n Bridge-backed account types and their connected accounts.\n\n - `items: { accounts: { accountID: string; bridge: object; user: user; network?: string; }[]; activeAccountCount: number; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges);\n```", + "## list\n\n`client.messages.list(chatID: string, cursor?: string, direction?: 'after' | 'before'): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages`\n\nList all messages in a chat with cursor-based pagination. Sorted by timestamp.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message);\n}\n```", perLanguage: { typescript: { - method: 'client.bridges.list', + method: 'client.messages.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges.items);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message.id);\n}", }, python: { - method: 'bridges.list', + method: 'messages.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nbridges = client.bridges.list()\nprint(bridges.items)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.messages.list(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\npage = page.items[0]\nprint(page.id)', }, go: { - method: 'client.Bridges.List', + method: 'client.Messages.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tbridges, err := client.Bridges.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", bridges.Items)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.List(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'bridges list', - example: "beeper-desktop-cli bridges list \\\n --access-token 'My Access Token'", + method: 'messages list', + example: + "beeper-desktop-cli messages list \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'bridges->list', + method: 'messages->list', example: - "bridges->list();\n\nvar_dump($bridges);", + "messages->list(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/bridges \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve_profile', - endpoint: '/_matrix/client/v3/profile/{userId}', - httpMethod: 'get', - summary: 'Get all profile information for a user.', - description: 'Get the complete profile for a user.', - stainlessPath: '(resource) matrix.users > (method) retrieve_profile', - qualified: 'client.matrix.users.retrieveProfile', - params: ['userId: string;'], - response: '{ avatar_url?: string; displayname?: string; m.tz?: string; }', + name: 'send', + endpoint: '/v1/chats/{chatID}/messages', + httpMethod: 'post', + summary: 'Send a message', + description: + 'Send a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.', + stainlessPath: '(resource) messages > (method) send', + qualified: 'client.messages.send', + params: [ + 'chatID: string;', + "attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; };", + 'replyToMessageID?: string;', + 'text?: string;', + ], + response: '{ chatID: string; pendingMessageID: string; }', markdown: - "## retrieve_profile\n\n`client.matrix.users.retrieveProfile(userId: string): { avatar_url?: string; displayname?: string; m.tz?: string; }`\n\n**get** `/_matrix/client/v3/profile/{userId}`\n\nGet the complete profile for a user.\n\n### Parameters\n\n- `userId: string`\n\n### Returns\n\n- `{ avatar_url?: string; displayname?: string; m.tz?: string; }`\n\n - `avatar_url?: string`\n - `displayname?: string`\n - `m.tz?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.users.retrieveProfile('@alice:example.com');\n\nconsole.log(response);\n```", + "## send\n\n`client.messages.send(chatID: string, attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }, replyToMessageID?: string, text?: string): { chatID: string; pendingMessageID: string; }`\n\n**post** `/v1/chats/{chatID}/messages`\n\nSend a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }`\n Single attachment to send with the message\n - `uploadID: string`\n Upload ID from uploadAsset endpoint. Required to reference uploaded files.\n - `duration?: number`\n Duration in seconds (optional override of cached value)\n - `fileName?: string`\n Filename (optional override of cached value)\n - `mimeType?: string`\n MIME type (optional override of cached value)\n - `size?: { height: number; width: number; }`\n Dimensions (optional override of cached value)\n - `type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'`\n Attachment type hint (image, video, audio, file, gif, voice-note, sticker). If omitted, auto-detected from mimeType\n\n- `replyToMessageID?: string`\n Provide a message ID to send this as a reply to an existing message\n\n- `text?: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n\n### Returns\n\n- `{ chatID: string; pendingMessageID: string; }`\n\n - `chatID: string`\n - `pendingMessageID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.users.retrieveProfile', + method: 'client.messages.send', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.users.retrieveProfile('@alice:example.com');\n\nconsole.log(response.avatar_url);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response.pendingMessageID);", }, python: { - method: 'matrix.users.retrieve_profile', + method: 'messages.send', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.users.retrieve_profile(\n "@alice:example.com",\n)\nprint(response.avatar_url)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.messages.send(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(response.pending_message_id)', }, go: { - method: 'client.Matrix.Users.GetProfile', + method: 'client.Messages.Send', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Users.GetProfile(context.TODO(), "@alice:example.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AvatarURL)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Messages.Send(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageSendParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.PendingMessageID)\n}\n', }, cli: { - method: 'users retrieve_profile', + method: 'messages send', example: - "beeper-desktop-cli matrix:users retrieve-profile \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com", + "beeper-desktop-cli messages send \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'matrix->users->retrieveProfile', + method: 'messages->send', example: - "matrix->users->retrieveProfile('@alice:example.com');\n\nvar_dump($response);", + "messages->send(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n attachment: [\n 'uploadID' => 'uploadID',\n 'duration' => 0,\n 'fileName' => 'fileName',\n 'mimeType' => 'mimeType',\n 'size' => ['height' => 0, 'width' => 0],\n 'type' => 'image',\n ],\n replyToMessageID: 'replyToMessageID',\n text: 'text',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/profile/$USER_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { name: 'retrieve', - endpoint: '/_matrix/client/v3/user/{userId}/account_data/{type}', + endpoint: '/v1/chats/{chatID}/messages/{messageID}', httpMethod: 'get', - summary: 'Get some account data for the user.', + summary: 'Retrieve a message', description: - 'Get some account data for the client. This config is only visible to the user\nthat set the account data.', - stainlessPath: '(resource) matrix.users.account_data > (method) retrieve', - qualified: 'client.matrix.users.accountData.retrieve', - params: ['userId: string;', 'type: string;'], - response: 'object', + 'Retrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.', + stainlessPath: '(resource) messages > (method) retrieve', + qualified: 'client.messages.retrieve', + params: ['chatID: string;', 'messageID: string;'], + response: + "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## retrieve\n\n`client.matrix.users.accountData.retrieve(userId: string, type: string): object`\n\n**get** `/_matrix/client/v3/user/{userId}/account_data/{type}`\n\nGet some account data for the client. This config is only visible to the user\nthat set the account data.\n\n### Parameters\n\n- `userId: string`\n\n- `type: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.users.accountData.retrieve('org.example.custom.config', { userId: '@alice:example.com' });\n\nconsole.log(accountData);\n```", + "## retrieve\n\n`client.messages.retrieve(chatID: string, messageID: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages/{messageID}`\n\nRetrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.retrieve('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });\n\nconsole.log(message);\n```", perLanguage: { typescript: { - method: 'client.matrix.users.accountData.retrieve', + method: 'client.messages.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.users.accountData.retrieve('org.example.custom.config', {\n userId: '@alice:example.com',\n});\n\nconsole.log(accountData);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst message = await client.messages.retrieve('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n});\n\nconsole.log(message.id);", }, python: { - method: 'matrix.users.account_data.retrieve', + method: 'messages.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.users.account_data.retrieve(\n type="org.example.custom.config",\n user_id="@alice:example.com",\n)\nprint(account_data)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nmessage = client.messages.retrieve(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(message.id)', }, go: { - method: 'client.Matrix.Users.AccountData.Get', + method: 'client.Messages.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Users.AccountData.Get(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.config",\n\t\tbeeperdesktopapi.MatrixUserAccountDataGetParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Get(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageGetParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message.ID)\n}\n', }, cli: { - method: 'account_data retrieve', + method: 'messages retrieve', example: - "beeper-desktop-cli matrix:users:account-data retrieve \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --type org.example.custom.config", + "beeper-desktop-cli messages retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", }, php: { - method: 'matrix->users->accountData->retrieve', + method: 'messages->retrieve', example: - "matrix->users->accountData->retrieve(\n 'org.example.custom.config', userID: '@alice:example.com'\n);\n\nvar_dump($accountData);", + "messages->retrieve(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com'\n);\n\nvar_dump($message);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/account_data/$TYPE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { name: 'update', - endpoint: '/_matrix/client/v3/user/{userId}/account_data/{type}', + endpoint: '/v1/chats/{chatID}/messages/{messageID}', httpMethod: 'put', - summary: 'Set some account data for the user.', - description: - 'Set some account data for the client. This config is only visible to the user\nthat set the account data. The config will be available to clients through the\ntop-level `account_data` field in the homeserver response to\n[/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).', - stainlessPath: '(resource) matrix.users.account_data > (method) update', - qualified: 'client.matrix.users.accountData.update', - params: ['userId: string;', 'type: string;', 'body: object;'], - response: 'object', + summary: 'Edit a message', + description: 'Edit the text content of an existing message. Messages with attachments cannot be edited.', + stainlessPath: '(resource) messages > (method) update', + qualified: 'client.messages.update', + params: ['chatID: string;', 'messageID: string;', 'text: string;'], + response: + "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## update\n\n`client.matrix.users.accountData.update(userId: string, type: string, body: object): object`\n\n**put** `/_matrix/client/v3/user/{userId}/account_data/{type}`\n\nSet some account data for the client. This config is only visible to the user\nthat set the account data. The config will be available to clients through the\ntop-level `account_data` field in the homeserver response to\n[/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).\n\n### Parameters\n\n- `userId: string`\n\n- `type: string`\n\n- `body: object`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.users.accountData.update('org.example.custom.config', {\n userId: '@alice:example.com',\n body: { custom_account_data_key: 'custom_config_value' },\n});\n\nconsole.log(accountData);\n```", + "## update\n\n`client.messages.update(chatID: string, messageID: string, text: string): object`\n\n**put** `/v1/chats/{chatID}/messages/{messageID}`\n\nEdit the text content of an existing message. Messages with attachments cannot be edited.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `text: string`\n New text content for the message\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.update('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x' });\n\nconsole.log(message);\n```", perLanguage: { typescript: { - method: 'client.matrix.users.accountData.update', + method: 'client.messages.update', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.users.accountData.update('org.example.custom.config', {\n userId: '@alice:example.com',\n body: { custom_account_data_key: 'custom_config_value' },\n});\n\nconsole.log(accountData);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst message = await client.messages.update('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n text: 'x',\n});\n\nconsole.log(message);", }, python: { - method: 'matrix.users.account_data.update', + method: 'messages.update', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.users.account_data.update(\n type="org.example.custom.config",\n user_id="@alice:example.com",\n body={\n "custom_account_data_key": "custom_config_value"\n },\n)\nprint(account_data)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nmessage = client.messages.update(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n text="x",\n)\nprint(message)', }, go: { - method: 'client.Matrix.Users.AccountData.Update', + method: 'client.Messages.Update', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Users.AccountData.Update(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.config",\n\t\tbeeperdesktopapi.MatrixUserAccountDataUpdateParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tBody: map[string]any{\n\t\t\t\t"custom_account_data_key": "custom_config_value",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Update(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageUpdateParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tText: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message)\n}\n', }, cli: { - method: 'account_data update', + method: 'messages update', example: - "beeper-desktop-cli matrix:users:account-data update \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --type org.example.custom.config \\\n --body '{custom_account_data_key: custom_config_value}'", + "beeper-desktop-cli messages update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --text x", }, php: { - method: 'matrix->users->accountData->update', + method: 'messages->update', example: - "matrix->users->accountData->update(\n 'org.example.custom.config',\n userID: '@alice:example.com',\n body: ['custom_account_data_key' => 'custom_config_value'],\n);\n\nvar_dump($accountData);", + "messages->update(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x'\n);\n\nvar_dump($message);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/account_data/$TYPE \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "custom_account_data_key": "custom_config_value"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "text": "x"\n }\'', }, }, }, { - name: 'create', - endpoint: '/_matrix/client/v3/createRoom', - httpMethod: 'post', - summary: 'Create a new room', - description: - "Create a new room with various configuration options.\n\nThe server MUST apply the normal state resolution rules when creating\nthe new room, including checking power levels for each event. It MUST\napply the events implied by the request in the following order:\n\n1. The `m.room.create` event itself. Must be the first event in the\n room.\n\n2. An `m.room.member` event for the creator to join the room. This is\n needed so the remaining events can be sent.\n\n3. A default `m.room.power_levels` event. Overridden by the\n `power_level_content_override` parameter.\n\n In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the room creator (and not\n other members) will be given permission to send state events.\n\n In room versions 12 and later, the room creator is given infinite\n power level and cannot be specified in the `users` field of\n `m.room.power_levels`, so is not listed explicitly.\n\n **Note**: For `trusted_private_chat`, the users specified in the\n `invite` parameter SHOULD also be appended to `additional_creators`\n by the server, per the `creation_content` parameter.\n\n If the room's version is 12 or higher, the power level for sending\n `m.room.tombstone` events MUST explicitly be higher than `state_default`.\n For example, set to 150 instead of 100.\n\n4. An `m.room.canonical_alias` event if `room_alias_name` is given.\n\n5. Events set by the `preset`. Currently these are the `m.room.join_rules`,\n `m.room.history_visibility`, and `m.room.guest_access` state events.\n\n6. Events listed in `initial_state`, in the order that they are\n listed.\n\n7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`\n state events).\n\n8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with\n `membership: invite` and `m.room.third_party_invite`).\n\nThe available presets do the following with respect to room state:\n\n| Preset | `join_rules` | `history_visibility` | `guest_access` | Other |\n|------------------------|--------------|----------------------|----------------|-------|\n| `private_chat` | `invite` | `shared` | `can_join` | |\n| `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. |\n| `public_chat` | `public` | `shared` | `forbidden` | |\n\nThe server will create a `m.room.create` event in the room with the\nrequesting user as the creator, alongside other keys provided in the\n`creation_content` or implied by behaviour of `creation_content`.", - stainlessPath: '(resource) matrix.rooms > (method) create', - qualified: 'client.matrix.rooms.create', - params: [ - 'creation_content?: object;', - 'initial_state?: { content: object; type: string; state_key?: string; }[];', - 'invite?: string[];', - 'invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[];', - 'is_direct?: boolean;', - 'name?: string;', - 'power_level_content_override?: object;', - "preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat';", - 'room_alias_name?: string;', - 'room_version?: string;', - 'topic?: string;', - "visibility?: 'public' | 'private';", - ], - response: '{ room_id: string; }', + name: 'delete', + endpoint: '/v1/chats/{chatID}/messages/{messageID}', + httpMethod: 'delete', + summary: 'Delete a message', + description: + 'Delete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.', + stainlessPath: '(resource) messages > (method) delete', + qualified: 'client.messages.delete', + params: ['chatID: string;', 'messageID: string;', 'forEveryone?: boolean;'], markdown: - "## create\n\n`client.matrix.rooms.create(creation_content?: object, initial_state?: { content: object; type: string; state_key?: string; }[], invite?: string[], invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[], is_direct?: boolean, name?: string, power_level_content_override?: object, preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat', room_alias_name?: string, room_version?: string, topic?: string, visibility?: 'public' | 'private'): { room_id: string; }`\n\n**post** `/_matrix/client/v3/createRoom`\n\nCreate a new room with various configuration options.\n\nThe server MUST apply the normal state resolution rules when creating\nthe new room, including checking power levels for each event. It MUST\napply the events implied by the request in the following order:\n\n1. The `m.room.create` event itself. Must be the first event in the\n room.\n\n2. An `m.room.member` event for the creator to join the room. This is\n needed so the remaining events can be sent.\n\n3. A default `m.room.power_levels` event. Overridden by the\n `power_level_content_override` parameter.\n\n In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the room creator (and not\n other members) will be given permission to send state events.\n\n In room versions 12 and later, the room creator is given infinite\n power level and cannot be specified in the `users` field of\n `m.room.power_levels`, so is not listed explicitly.\n\n **Note**: For `trusted_private_chat`, the users specified in the\n `invite` parameter SHOULD also be appended to `additional_creators`\n by the server, per the `creation_content` parameter.\n\n If the room's version is 12 or higher, the power level for sending\n `m.room.tombstone` events MUST explicitly be higher than `state_default`.\n For example, set to 150 instead of 100.\n\n4. An `m.room.canonical_alias` event if `room_alias_name` is given.\n\n5. Events set by the `preset`. Currently these are the `m.room.join_rules`,\n `m.room.history_visibility`, and `m.room.guest_access` state events.\n\n6. Events listed in `initial_state`, in the order that they are\n listed.\n\n7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`\n state events).\n\n8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with\n `membership: invite` and `m.room.third_party_invite`).\n\nThe available presets do the following with respect to room state:\n\n| Preset | `join_rules` | `history_visibility` | `guest_access` | Other |\n|------------------------|--------------|----------------------|----------------|-------|\n| `private_chat` | `invite` | `shared` | `can_join` | |\n| `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. |\n| `public_chat` | `public` | `shared` | `forbidden` | |\n\nThe server will create a `m.room.create` event in the room with the\nrequesting user as the creator, alongside other keys provided in the\n`creation_content` or implied by behaviour of `creation_content`.\n\n### Parameters\n\n- `creation_content?: object`\n Extra keys, such as `m.federate`, to be added to the content\nof the [`m.room.create`](https://spec.matrix.org/v1.18/client-server-api/#mroomcreate) event.\n\nThe server will overwrite the following\nkeys: `creator`, `room_version`. Future versions of the specification\nmay allow the server to overwrite other keys.\n\nWhen using the `trusted_private_chat` preset, the server SHOULD combine\n`additional_creators` specified here and the `invite` array into the\neventual `m.room.create` event's `additional_creators`, deduplicating\nbetween the two parameters.\n\n- `initial_state?: { content: object; type: string; state_key?: string; }[]`\n A list of state events to set in the new room. This allows\nthe user to override the default state events set in the new\nroom. The expected format of the state events are an object\nwith type, state_key and content keys set.\n\nTakes precedence over events set by `preset`, but gets\noverridden by `name` and `topic` keys.\n\n- `invite?: string[]`\n A list of user IDs to invite to the room. This will tell the\nserver to invite everyone in the list to the newly created room.\n\n- `invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[]`\n A list of objects representing third-party IDs to invite into\nthe room.\n\n- `is_direct?: boolean`\n This flag makes the server set the `is_direct` flag on the\n`m.room.member` events sent to the users in `invite` and\n`invite_3pid`. See [Direct Messaging](https://spec.matrix.org/v1.18/client-server-api/#direct-messaging) for more information.\n\n- `name?: string`\n If this is included, an [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname) event\nwill be sent into the room to indicate the name for the room.\nThis overwrites any [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname)\nevent in `initial_state`.\n\n- `power_level_content_override?: object`\n The power level content to override in the default power level\nevent. This object is applied on top of the generated\n[`m.room.power_levels`](https://spec.matrix.org/v1.18/client-server-api/#mroompower_levels)\nevent content prior to it being sent to the room. Defaults to\noverriding nothing.\n\n- `preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat'`\n Convenience parameter for setting various default state events\nbased on a preset.\n\nIf unspecified, the server should use the `visibility` to determine\nwhich preset to use. A visibility of `public` equates to a preset of\n`public_chat` and `private` visibility equates to a preset of\n`private_chat`.\n\n- `room_alias_name?: string`\n The desired room alias **local part**. If this is included, a\nroom alias will be created and mapped to the newly created\nroom. The alias will belong on the *same* homeserver which\ncreated the room. For example, if this was set to \"foo\" and\nsent to the homeserver \"example.com\" the complete room alias\nwould be `#foo:example.com`.\n\nThe complete room alias will become the canonical alias for\nthe room and an `m.room.canonical_alias` event will be sent\ninto the room.\n\n- `room_version?: string`\n The room version to set for the room. If not provided, the homeserver is\nto use its configured default. If provided, the homeserver will return a\n400 error with the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not\nsupport the room version.\n\n- `topic?: string`\n If this is included, an [`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic)\nevent with a `text/plain` mimetype will be sent into the room\nto indicate the topic for the room. This overwrites any\n[`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic) event in `initial_state`.\n\n- `visibility?: 'public' | 'private'`\n The room's visibility in the server's\n[published room directory](https://spec.matrix.org/v1.18/client-server-api#published-room-directory).\nDefaults to `private`.\n\n### Returns\n\n- `{ room_id: string; }`\n Information about the newly created room.\n\n - `room_id: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst room = await client.matrix.rooms.create();\n\nconsole.log(room);\n```", + "## delete\n\n`client.messages.delete(chatID: string, messageID: string, forEveryone?: boolean): void`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}`\n\nDelete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `forEveryone?: boolean`\n True to request deletion for everyone when the network supports it; false to delete only for the authenticated user when supported.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' })\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.create', + method: 'client.messages.delete', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst room = await client.matrix.rooms.create();\n\nconsole.log(room.room_id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });", }, python: { - method: 'matrix.rooms.create', + method: 'messages.delete', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nroom = client.matrix.rooms.create()\nprint(room.room_id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.messages.delete(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', }, go: { - method: 'client.Matrix.Rooms.New', + method: 'client.Messages.Delete', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\troom, err := client.Matrix.Rooms.New(context.TODO(), beeperdesktopapi.MatrixRoomNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", room.RoomID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Messages.Delete(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, cli: { - method: 'rooms create', - example: "beeper-desktop-cli matrix:rooms create \\\n --access-token 'My Access Token'", + method: 'messages delete', + example: + "beeper-desktop-cli messages delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", }, php: { - method: 'matrix->rooms->create', + method: 'messages->delete', example: - "matrix->rooms->create(\n creationContent: ['m.federate' => false],\n initialState: [\n ['content' => (object) [], 'type' => 'type', 'stateKey' => 'state_key']\n ],\n invite: ['string'],\n invite3pid: [\n [\n 'address' => 'cheeky@monkey.com',\n 'idAccessToken' => 'abc123_OpaqueString',\n 'idServer' => 'matrix.org',\n 'medium' => 'email',\n ],\n ],\n isDirect: true,\n name: 'The Grand Duke Pub',\n powerLevelContentOverride: (object) [],\n preset: 'public_chat',\n roomAliasName: 'thepub',\n roomVersion: '1',\n topic: 'All about happy hour',\n visibility: 'public',\n);\n\nvar_dump($room);", + "messages->delete(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', forEveryone: true\n);\n\nvar_dump($result);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/createRoom \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "creation_content": {\n "m.federate": false\n },\n "name": "The Grand Duke Pub",\n "preset": "public_chat",\n "room_alias_name": "thepub",\n "room_version": "1",\n "topic": "All about happy hour"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'join', - endpoint: '/_matrix/client/v3/join/{roomIdOrAlias}', + name: 'download', + endpoint: '/v1/assets/download', httpMethod: 'post', - summary: 'Join the requesting user to a particular room.', + summary: 'Download a file', description: - "*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.\n\nThis API starts a user's participation in a particular room, if that user\nis allowed to participate in that room. After this call, the client is\nallowed to see all current state events in the room, and all subsequent\nevents associated with the room until the user leaves the room.\n\nAfter a user has joined a room, the room will appear as an entry in the\nresponse of the [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync)\nand [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) APIs.", - stainlessPath: '(resource) matrix.rooms > (method) join', - qualified: 'client.matrix.rooms.join', - params: [ - 'roomIdOrAlias: string;', - 'via?: string[];', - 'reason?: string;', - 'third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; };', - ], - response: '{ room_id: string; }', + 'Download a Matrix file using its mxc:// or localmxc:// URL to the device running Beeper Desktop and return the local file URL.', + stainlessPath: '(resource) assets > (method) download', + qualified: 'client.assets.download', + params: ['url: string;'], + response: '{ error?: string; srcURL?: string; }', markdown: - "## join\n\n`client.matrix.rooms.join(roomIdOrAlias: string, via?: string[], reason?: string, third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; }): { room_id: string; }`\n\n**post** `/_matrix/client/v3/join/{roomIdOrAlias}`\n\n*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.\n\nThis API starts a user's participation in a particular room, if that user\nis allowed to participate in that room. After this call, the client is\nallowed to see all current state events in the room, and all subsequent\nevents associated with the room until the user leaves the room.\n\nAfter a user has joined a room, the room will appear as an entry in the\nresponse of the [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync)\nand [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) APIs.\n\n### Parameters\n\n- `roomIdOrAlias: string`\n\n- `via?: string[]`\n The servers to attempt to join the room through. One of the servers\nmust be participating in the room.\n\n- `reason?: string`\n Optional reason to be included as the `reason` on the subsequent\nmembership event.\n\n- `third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; }`\n A signature of an `m.third_party_invite` token to prove that this user\nowns a third-party identity which has been invited to the room.\n - `token: string`\n The state key of the m.third_party_invite event.\n - `mxid: string`\n The Matrix ID of the invitee.\n - `sender: string`\n The Matrix ID of the user who issued the invite.\n - `signatures: object`\n A signatures object containing a signature of the entire signed object.\n\n### Returns\n\n- `{ room_id: string; }`\n\n - `room_id: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.rooms.join('!monkeys:matrix.org');\n\nconsole.log(response);\n```", + "## download\n\n`client.assets.download(url: string): { error?: string; srcURL?: string; }`\n\n**post** `/v1/assets/download`\n\nDownload a Matrix file using its mxc:// or localmxc:// URL to the device running Beeper Desktop and return the local file URL.\n\n### Parameters\n\n- `url: string`\n Matrix content URL (mxc:// or localmxc://) for the file to download.\n\n### Returns\n\n- `{ error?: string; srcURL?: string; }`\n\n - `error?: string`\n - `srcURL?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.join', + method: 'client.assets.download', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.rooms.join('!monkeys:matrix.org');\n\nconsole.log(response.room_id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response.error);", }, python: { - method: 'matrix.rooms.join', + method: 'assets.download', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.rooms.join(\n room_id_or_alias="!monkeys:matrix.org",\n)\nprint(response.room_id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.download(\n url="mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n)\nprint(response.error)', }, go: { - method: 'client.Matrix.Rooms.Join', + method: 'client.Assets.Download', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Rooms.Join(\n\t\tcontext.TODO(),\n\t\t"!monkeys:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomJoinParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.RoomID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Download(context.TODO(), beeperdesktopapi.AssetDownloadParams{\n\t\tURL: "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Error)\n}\n', }, cli: { - method: 'rooms join', + method: 'assets download', example: - "beeper-desktop-cli matrix:rooms join \\\n --access-token 'My Access Token' \\\n --room-id-or-alias '!monkeys:matrix.org'", + "beeper-desktop-cli assets download \\\n --access-token 'My Access Token' \\\n --url mxc://example.org/Q4x9CqGz1pB3Oa6XgJ", }, php: { - method: 'matrix->rooms->join', + method: 'assets->download', example: - "matrix->rooms->join(\n '!monkeys:matrix.org',\n via: ['string'],\n reason: 'Looking for support',\n thirdPartySigned: [\n 'token' => 'random8nonce',\n 'mxid' => 'bob',\n 'sender' => 'alice',\n 'signatures' => ['example.org' => ['ed25519:0' => 'some9signature']],\n ],\n);\n\nvar_dump($response);", + "assets->download(\n url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/join/$ROOM_ID_OR_ALIAS \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reason": "Looking for support"\n }\'', + 'curl http://localhost:23373/v1/assets/download \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "url": "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ"\n }\'', }, }, }, { - name: 'leave', - endpoint: '/_matrix/client/v3/rooms/{roomId}/leave', + name: 'upload', + endpoint: '/v1/assets/upload', httpMethod: 'post', - summary: 'Stop the requesting user participating in a particular room.', + summary: 'Upload a file', description: - "This API stops a user participating in a particular room.\n\nIf the user was already in the room, they will no longer be able to see\nnew events in the room. If the room requires an invite to join, they\nwill need to be re-invited before they can re-join.\n\nIf the user was invited to the room, but had not joined, this call\nserves to reject the invite.\n\nServers MAY additionally forget the room when this endpoint is called –\njust as if the user had also invoked [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget).\nServers that do this, MUST inform clients about this behavior using the\n[`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability)\ncapability.\n\nIf the server doesn't automatically forget the room, the user will still be\nallowed to retrieve history from the room which they were previously allowed\nto see.", - stainlessPath: '(resource) matrix.rooms > (method) leave', - qualified: 'client.matrix.rooms.leave', - params: ['roomId: string;', 'reason?: string;'], - response: 'object', + '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.', + stainlessPath: '(resource) assets > (method) upload', + qualified: 'client.assets.upload', + params: ['file: string;', 'fileName?: string;', 'mimeType?: string;'], + response: + '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', markdown: - "## leave\n\n`client.matrix.rooms.leave(roomId: string, reason?: string): object`\n\n**post** `/_matrix/client/v3/rooms/{roomId}/leave`\n\nThis API stops a user participating in a particular room.\n\nIf the user was already in the room, they will no longer be able to see\nnew events in the room. If the room requires an invite to join, they\nwill need to be re-invited before they can re-join.\n\nIf the user was invited to the room, but had not joined, this call\nserves to reject the invite.\n\nServers MAY additionally forget the room when this endpoint is called –\njust as if the user had also invoked [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget).\nServers that do this, MUST inform clients about this behavior using the\n[`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability)\ncapability.\n\nIf the server doesn't automatically forget the room, the user will still be\nallowed to retrieve history from the room which they were previously allowed\nto see.\n\n### Parameters\n\n- `roomId: string`\n\n- `reason?: string`\n Optional reason to be included as the `reason` on the subsequent\nmembership event.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.rooms.leave('!nkl290a:matrix.org');\n\nconsole.log(response);\n```", + "## upload\n\n`client.assets.upload(file: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload`\n\nUpload 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.\n\n### Parameters\n\n- `file: string`\n The file to upload (max 500 MB).\n\n- `fileName?: string`\n Original filename. Defaults to the uploaded file name if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.leave', + method: 'client.assets.upload', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.rooms.leave('!nkl290a:matrix.org');\n\nconsole.log(response);", + "import fs from 'fs';\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response.width);", }, python: { - method: 'matrix.rooms.leave', + method: 'assets.upload', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.rooms.leave(\n room_id="!nkl290a:matrix.org",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.upload(\n file=b"Example data",\n)\nprint(response.width)', }, go: { - method: 'client.Matrix.Rooms.Leave', + method: 'client.Assets.Upload', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Rooms.Leave(\n\t\tcontext.TODO(),\n\t\t"!nkl290a:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomLeaveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"bytes"\n\t"context"\n\t"fmt"\n\t"io"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Upload(context.TODO(), beeperdesktopapi.AssetUploadParams{\n\t\tFile: io.Reader(bytes.NewBuffer([]byte("Example data"))),\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', }, cli: { - method: 'rooms leave', + method: 'assets upload', example: - "beeper-desktop-cli matrix:rooms leave \\\n --access-token 'My Access Token' \\\n --room-id '!nkl290a:matrix.org'", + "beeper-desktop-cli assets upload \\\n --access-token 'My Access Token' \\\n --file 'Example data'", }, php: { - method: 'matrix->rooms->leave', + method: 'assets->upload', example: - "matrix->rooms->leave(\n '!nkl290a:matrix.org', reason: 'Saying farewell - thanks for the support!'\n);\n\nvar_dump($response);", + "assets->upload(\n file: FileParam::fromString('Example data', filename: uniqid('file-upload-', true)),\n fileName: 'fileName',\n mimeType: 'mimeType',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/leave \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reason": "Saying farewell - thanks for the support!"\n }\'', + "curl http://localhost:23373/v1/assets/upload \\\n -H 'Content-Type: multipart/form-data' \\\n -H \"Authorization: Bearer $BEEPER_ACCESS_TOKEN\" \\\n -F 'file=@/path/to/file'", }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', - httpMethod: 'get', - summary: 'Get some account data for the user that is specific to a room.', + name: 'upload_base64', + endpoint: '/v1/assets/upload/base64', + httpMethod: 'post', + summary: 'Upload a file (base64)', description: - 'Get some account data for the client on a given room. This config is only\nvisible to the user that set the account data.', - stainlessPath: '(resource) matrix.rooms.account_data > (method) retrieve', - qualified: 'client.matrix.rooms.accountData.retrieve', - params: ['userId: string;', 'roomId: string;', 'type: string;'], - response: 'object', + '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.', + stainlessPath: '(resource) assets > (method) upload_base64', + qualified: 'client.assets.uploadBase64', + params: ['content: string;', 'fileName?: string;', 'mimeType?: string;'], + response: + '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', markdown: - "## retrieve\n\n`client.matrix.rooms.accountData.retrieve(userId: string, roomId: string, type: string): object`\n\n**get** `/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}`\n\nGet some account data for the client on a given room. This config is only\nvisible to the user that set the account data.\n\n### Parameters\n\n- `userId: string`\n\n- `roomId: string`\n\n- `type: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.rooms.accountData.retrieve('org.example.custom.room.config', { userId: '@alice:example.com', roomId: '!726s6s6q:example.com' });\n\nconsole.log(accountData);\n```", + "## upload_base64\n\n`client.assets.uploadBase64(content: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload/base64`\n\nUpload 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.\n\n### Parameters\n\n- `content: string`\n Base64-encoded file content (max ~500MB decoded)\n\n- `fileName?: string`\n Original filename. Generated if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.accountData.retrieve', + method: 'client.assets.uploadBase64', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.rooms.accountData.retrieve(\n 'org.example.custom.room.config',\n { userId: '@alice:example.com', roomId: '!726s6s6q:example.com' },\n);\n\nconsole.log(accountData);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response.width);", }, python: { - method: 'matrix.rooms.account_data.retrieve', + method: 'assets.upload_base64', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.rooms.account_data.retrieve(\n type="org.example.custom.room.config",\n user_id="@alice:example.com",\n room_id="!726s6s6q:example.com",\n)\nprint(account_data)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.upload_base64(\n content="x",\n)\nprint(response.width)', }, go: { - method: 'client.Matrix.Rooms.AccountData.Get', + method: 'client.Assets.UploadBase64', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Rooms.AccountData.Get(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.room.config",\n\t\tbeeperdesktopapi.MatrixRoomAccountDataGetParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tRoomID: "!726s6s6q:example.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.UploadBase64(context.TODO(), beeperdesktopapi.AssetUploadBase64Params{\n\t\tContent: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', }, cli: { - method: 'account_data retrieve', + method: 'assets upload_base64', example: - "beeper-desktop-cli matrix:rooms:account-data retrieve \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --room-id '!726s6s6q:example.com' \\\n --type org.example.custom.room.config", + "beeper-desktop-cli assets upload-base64 \\\n --access-token 'My Access Token' \\\n --content x", }, php: { - method: 'matrix->rooms->accountData->retrieve', + method: 'assets->uploadBase64', example: - "matrix->rooms->accountData->retrieve(\n 'org.example.custom.room.config',\n userID: '@alice:example.com',\n roomID: '!726s6s6q:example.com',\n);\n\nvar_dump($accountData);", + "assets->uploadBase64(\n content: 'x', fileName: 'fileName', mimeType: 'mimeType'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/rooms/$ROOM_ID/account_data/$TYPE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/assets/upload/base64 \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "content": "x"\n }\'', }, }, }, { - name: 'update', - endpoint: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', - httpMethod: 'put', - summary: 'Set some account data for the user that is specific to a room.', + name: 'serve', + endpoint: '/v1/assets/serve', + httpMethod: 'get', + summary: 'Serve a file', description: - 'Set some account data for the client on a given room. This config is only\nvisible to the user that set the account data. The config will be delivered to\nclients in the per-room entries via [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).', - stainlessPath: '(resource) matrix.rooms.account_data > (method) update', - qualified: 'client.matrix.rooms.accountData.update', - params: ['userId: string;', 'roomId: string;', 'type: string;', 'body: object;'], - response: 'object', + 'Stream a file given an mxc://, localmxc://, or file:// URL. Downloads first if not cached. Supports Range requests for seeking in large files.', + stainlessPath: '(resource) assets > (method) serve', + qualified: 'client.assets.serve', + params: ['url: string;'], + response: 'string', markdown: - "## update\n\n`client.matrix.rooms.accountData.update(userId: string, roomId: string, type: string, body: object): object`\n\n**put** `/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}`\n\nSet some account data for the client on a given room. This config is only\nvisible to the user that set the account data. The config will be delivered to\nclients in the per-room entries via [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).\n\n### Parameters\n\n- `userId: string`\n\n- `roomId: string`\n\n- `type: string`\n\n- `body: object`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.rooms.accountData.update('org.example.custom.room.config', {\n userId: '@alice:example.com',\n roomId: '!726s6s6q:example.com',\n body: { custom_account_data_key: 'custom_account_data_value' },\n});\n\nconsole.log(accountData);\n```", + "## serve\n\n`client.assets.serve(url: string): string`\n\n**get** `/v1/assets/serve`\n\nStream a file given an mxc://, localmxc://, or file:// URL. Downloads first if not cached. Supports Range requests for seeking in large files.\n\n### Parameters\n\n- `url: string`\n File URL to serve. Accepts mxc://, localmxc://, or file:// URLs.\n\n### Returns\n\n- `string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.serve({ url: 'x' });\n\nconsole.log(response);\n\nconst content = await response.blob()\nconsole.log(content)\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.accountData.update', + method: 'client.assets.serve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.rooms.accountData.update('org.example.custom.room.config', {\n userId: '@alice:example.com',\n roomId: '!726s6s6q:example.com',\n body: { custom_account_data_key: 'custom_account_data_value' },\n});\n\nconsole.log(accountData);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.serve({ url: 'x' });\n\nconsole.log(response);\n\nconst content = await response.blob();\nconsole.log(content);", }, python: { - method: 'matrix.rooms.account_data.update', + method: 'assets.serve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.rooms.account_data.update(\n type="org.example.custom.room.config",\n user_id="@alice:example.com",\n room_id="!726s6s6q:example.com",\n body={\n "custom_account_data_key": "custom_account_data_value"\n },\n)\nprint(account_data)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.serve(\n url="x",\n)\nprint(response)\ncontent = response.read()\nprint(content)', }, go: { - method: 'client.Matrix.Rooms.AccountData.Update', + method: 'client.Assets.Serve', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Rooms.AccountData.Update(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.room.config",\n\t\tbeeperdesktopapi.MatrixRoomAccountDataUpdateParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tRoomID: "!726s6s6q:example.com",\n\t\t\tBody: map[string]any{\n\t\t\t\t"custom_account_data_key": "custom_account_data_value",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Serve(context.TODO(), beeperdesktopapi.AssetServeParams{\n\t\tURL: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'account_data update', - example: - "beeper-desktop-cli matrix:rooms:account-data update \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --room-id '!726s6s6q:example.com' \\\n --type org.example.custom.room.config \\\n --body '{custom_account_data_key: custom_account_data_value}'", + method: 'assets serve', + example: "beeper-desktop-cli assets serve \\\n --access-token 'My Access Token' \\\n --url x", }, php: { - method: 'matrix->rooms->accountData->update', + method: 'assets->serve', example: - "matrix->rooms->accountData->update(\n 'org.example.custom.room.config',\n userID: '@alice:example.com',\n roomID: '!726s6s6q:example.com',\n body: ['custom_account_data_key' => 'custom_account_data_value'],\n);\n\nvar_dump($accountData);", + "assets->serve(url: 'x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/rooms/$ROOM_ID/account_data/$TYPE \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "custom_account_data_key": "custom_account_data_value"\n }\'', + 'curl http://localhost:23373/v1/assets/serve \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'list', - endpoint: '/_matrix/client/v3/rooms/{roomId}/state', + name: 'retrieve', + endpoint: '/v1/info', httpMethod: 'get', - summary: 'Get all state events in the current state of a room.', - description: 'Get the state events for the current state of a room.', - stainlessPath: '(resource) matrix.rooms.state > (method) list', - qualified: 'client.matrix.rooms.state.list', - params: ['roomId: string;'], + summary: 'Retrieve server info', + description: + 'Returns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.', + stainlessPath: '(resource) info > (method) retrieve', + qualified: 'client.info.retrieve', response: - '{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }[]', + '{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }', markdown: - "## list\n\n`client.matrix.rooms.state.list(roomId: string): { content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: object; }[]`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/state`\n\nGet the state events for the current state of a room.\n\n### Parameters\n\n- `roomId: string`\n\n### Returns\n\n- `{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }[]`\n If the user is a member of the room this will be the\ncurrent state of the room as a list of events. If the user\nhas left the room then this will be the state of the room\nwhen they left as a list of events.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst states = await client.matrix.rooms.state.list('!636q39766251:example.com');\n\nconsole.log(states);\n```", + "## retrieve\n\n`client.info.retrieve(): { app: object; endpoints: object; platform: object; server: object; }`\n\n**get** `/v1/info`\n\nReturns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.\n\n### Returns\n\n- `{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }`\n\n - `app: { bundle_id: string; name: string; version: string; }`\n - `endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }`\n - `platform: { arch: string; os: string; release?: string; }`\n - `server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.state.list', + method: 'client.info.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst states = await client.matrix.rooms.state.list('!636q39766251:example.com');\n\nconsole.log(states);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info.app);", }, python: { - method: 'matrix.rooms.state.list', + method: 'info.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nstates = client.matrix.rooms.state.list(\n "!636q39766251:example.com",\n)\nprint(states)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\ninfo = client.info.retrieve()\nprint(info.app)', }, go: { - method: 'client.Matrix.Rooms.State.List', + method: 'client.Info.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tstates, err := client.Matrix.Rooms.State.List(context.TODO(), "!636q39766251:example.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", states)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tinfo, err := client.Info.Get(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", info.App)\n}\n', }, cli: { - method: 'state list', - example: - "beeper-desktop-cli matrix:rooms:state list \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:example.com'", - }, + method: 'info retrieve', + example: "beeper-desktop-cli info retrieve \\\n --access-token 'My Access Token'", + }, php: { - method: 'matrix->rooms->state->list', + method: 'info->retrieve', example: - "matrix->rooms->state->list('!636q39766251:example.com');\n\nvar_dump($states);", + "info->retrieve();\n\nvar_dump($info);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/state \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/info \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}', + name: 'status', + endpoint: '/v1/app/status', httpMethod: 'get', - summary: 'Get the state identified by the type and key.', + summary: 'Get app onboarding status', description: - 'Looks up the contents of a state event in a room. If the user is\njoined to the room then the state is taken from the current\nstate of the room. If the user has left the room then the state is\ntaken from the state of the room when they left.', - stainlessPath: '(resource) matrix.rooms.state > (method) retrieve', - qualified: 'client.matrix.rooms.state.retrieve', - params: ['roomId: string;', 'eventType: string;', 'stateKey: string;', "format?: 'content' | 'event';"], - response: 'object', + 'Return the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.', + stainlessPath: '(resource) app > (method) status', + qualified: 'client.app.status', + response: + "{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }", markdown: - "## retrieve\n\n`client.matrix.rooms.state.retrieve(roomId: string, eventType: string, stateKey: string, format?: 'content' | 'event'): object`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}`\n\nLooks up the contents of a state event in a room. If the user is\njoined to the room then the state is taken from the current\nstate of the room. If the user has left the room then the state is\ntaken from the state of the room when they left.\n\n### Parameters\n\n- `roomId: string`\n\n- `eventType: string`\n\n- `stateKey: string`\n\n- `format?: 'content' | 'event'`\n The format to use for the returned data. `content` (the default) will\nreturn only the content of the state event. `event` will return the entire\nevent in the usual format suitable for clients, including fields like event\nID, sender and timestamp.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst state = await client.matrix.rooms.state.retrieve('state_key', { roomId: '!636q39766251:example.com', eventType: 'm.room.name' });\n\nconsole.log(state);\n```", + "## status\n\n`client.app.status(): { e2ee: object; state: string; matrix?: object; verification?: object; }`\n\n**get** `/v1/app/status`\n\nReturn the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.\n\n### Returns\n\n- `{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n - `e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }`\n - `state: string`\n - `matrix?: { deviceID: string; homeserver: string; userID: string; }`\n - `verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.status();\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.state.retrieve', + method: 'client.app.status', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst state = await client.matrix.rooms.state.retrieve('state_key', {\n roomId: '!636q39766251:example.com',\n eventType: 'm.room.name',\n});\n\nconsole.log(state);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.status();\n\nconsole.log(response.e2ee);", }, python: { - method: 'matrix.rooms.state.retrieve', + method: 'app.status', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nstate = client.matrix.rooms.state.retrieve(\n state_key="state_key",\n room_id="!636q39766251:example.com",\n event_type="m.room.name",\n)\nprint(state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.status()\nprint(response.e2ee)', }, go: { - method: 'client.Matrix.Rooms.State.Get', + method: 'client.App.Status', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tstate, err := client.Matrix.Rooms.State.Get(\n\t\tcontext.TODO(),\n\t\t"state_key",\n\t\tbeeperdesktopapi.MatrixRoomStateGetParams{\n\t\t\tRoomID: "!636q39766251:example.com",\n\t\t\tEventType: "m.room.name",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", state)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Status(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.E2ee)\n}\n', }, cli: { - method: 'state retrieve', - example: - "beeper-desktop-cli matrix:rooms:state retrieve \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:example.com' \\\n --event-type m.room.name \\\n --state-key state_key", + method: 'app status', + example: "beeper-desktop-cli app status \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->rooms->state->retrieve', + method: 'app->status', example: - "matrix->rooms->state->retrieve(\n 'state_key',\n roomID: '!636q39766251:example.com',\n eventType: 'm.room.name',\n format: 'content',\n);\n\nvar_dump($state);", + "app->status();\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/state/$EVENT_TYPE/$STATE_KEY \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/status \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/v3/rooms/{roomId}/event/{eventId}', - httpMethod: 'get', - summary: 'Get a single event by event ID.', - description: - 'Get a single event based on `roomId/eventId`. You must have permission to\nretrieve this event e.g. by being a member in the room for this event.', - stainlessPath: '(resource) matrix.rooms.events > (method) retrieve', - qualified: 'client.matrix.rooms.events.retrieve', - params: ['roomId: string;', 'eventId: string;'], - response: - '{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }', + name: 'start', + endpoint: '/v1/app/login/start', + httpMethod: 'post', + summary: 'Start app login', + description: 'Start a first-party Beeper Desktop sign-in session.', + stainlessPath: '(resource) app.login > (method) start', + qualified: 'client.app.login.start', + response: '{ request: string; type: string[]; }', markdown: - "## retrieve\n\n`client.matrix.rooms.events.retrieve(roomId: string, eventId: string): { content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: object; }`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/event/{eventId}`\n\nGet a single event based on `roomId/eventId`. You must have permission to\nretrieve this event e.g. by being a member in the room for this event.\n\n### Parameters\n\n- `roomId: string`\n\n- `eventId: string`\n\n### Returns\n\n- `{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }`\n The format used for events when they are returned from a homeserver to a client\nvia the Client-Server API, or sent to an Application Service via the Application Services API.\n\n - `content: object`\n - `event_id: string`\n - `origin_server_ts: number`\n - `room_id: string`\n - `sender: string`\n - `type: string`\n - `state_key?: string`\n - `unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst event = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', { roomId: '!636q39766251:matrix.org' });\n\nconsole.log(event);\n```", + "## start\n\n`client.app.login.start(): { request: string; type: string[]; }`\n\n**post** `/v1/app/login/start`\n\nStart a first-party Beeper Desktop sign-in session.\n\n### Returns\n\n- `{ request: string; type: string[]; }`\n\n - `request: string`\n - `type: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.events.retrieve', + method: 'client.app.login.start', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst event = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', {\n roomId: '!636q39766251:matrix.org',\n});\n\nconsole.log(event.event_id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response.request);", }, python: { - method: 'matrix.rooms.events.retrieve', + method: 'app.login.start', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nevent = client.matrix.rooms.events.retrieve(\n event_id="$asfDuShaf7Gafaw:matrix.org",\n room_id="!636q39766251:matrix.org",\n)\nprint(event.event_id)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.start()\nprint(response.request)', }, go: { - method: 'client.Matrix.Rooms.Events.Get', + method: 'client.App.Login.Start', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tevent, err := client.Matrix.Rooms.Events.Get(\n\t\tcontext.TODO(),\n\t\t"$asfDuShaf7Gafaw:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomEventGetParams{\n\t\t\tRoomID: "!636q39766251:matrix.org",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", event.EventID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Start(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Request)\n}\n', }, cli: { - method: 'events retrieve', - example: - "beeper-desktop-cli matrix:rooms:events retrieve \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:matrix.org' \\\n --event-id '$asfDuShaf7Gafaw:matrix.org'", + method: 'login start', + example: "beeper-desktop-cli app:login start \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->rooms->events->retrieve', + method: 'app->login->start', example: - "matrix->rooms->events->retrieve(\n '$asfDuShaf7Gafaw:matrix.org', roomID: '!636q39766251:matrix.org'\n);\n\nvar_dump($event);", + "app->login->start();\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/event/$EVENT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'whoami', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami', - httpMethod: 'get', - summary: 'Get info about the bridge and your logins.', - description: - 'Get all info that is useful for presenting this bridge in a manager interface.\n* Server details: remote network details, available login flows, homeserver name, bridge bot user ID, command prefix\n* User details: management room ID, list of logins with current state and info\n', - stainlessPath: '(resource) matrix.bridges.auth > (method) whoami', - qualified: 'client.matrix.bridges.auth.whoami', - params: ['bridgeID: string;'], - response: - "{ bridge_bot: string; command_prefix: string; homeserver: string; login_flows: { id: string; description: string; name: string; }[]; logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]; network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }; management_room?: string; }", + name: 'email', + endpoint: '/v1/app/login/email', + httpMethod: 'post', + summary: 'Send login code', + description: 'Send a sign-in code to the user email address.', + stainlessPath: '(resource) app.login > (method) email', + qualified: 'client.app.login.email', + params: ['email: string;', 'request: string;'], + response: 'object', markdown: - "## whoami\n\n`client.matrix.bridges.auth.whoami(bridgeID: string): { bridge_bot: string; command_prefix: string; homeserver: string; login_flows: object[]; logins: object[]; network: object; management_room?: string; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami`\n\nGet all info that is useful for presenting this bridge in a manager interface.\n* Server details: remote network details, available login flows, homeserver name, bridge bot user ID, command prefix\n* User details: management room ID, list of logins with current state and info\n\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ bridge_bot: string; command_prefix: string; homeserver: string; login_flows: { id: string; description: string; name: string; }[]; logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]; network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }; management_room?: string; }`\n Info about the bridge and user\n\n - `bridge_bot: string`\n - `command_prefix: string`\n - `homeserver: string`\n - `login_flows: { id: string; description: string; name: string; }[]`\n - `logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]`\n - `network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }`\n - `management_room?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.whoami('bridgeID');\n\nconsole.log(response);\n```", + "## email\n\n`client.app.login.email(email: string, request: string): object`\n\n**post** `/v1/app/login/email`\n\nSend a sign-in code to the user email address.\n\n### Parameters\n\n- `email: string`\n Email address to send the sign-in code to.\n\n- `request: string`\n Login request ID returned by the start step.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.whoami', + method: 'client.app.login.email', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.whoami('bridgeID');\n\nconsole.log(response.bridge_bot);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);", }, python: { - method: 'matrix.bridges.auth.whoami', + method: 'app.login.email', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.whoami(\n "bridgeID",\n)\nprint(response.bridge_bot)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.email(\n email="dev@stainless.com",\n request="request",\n)\nprint(response)', }, go: { - method: 'client.Matrix.Bridges.Auth.Whoami', + method: 'client.App.Login.Email', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.Whoami(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.BridgeBot)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Email(context.TODO(), beeperdesktopapi.AppLoginEmailParams{\n\t\tEmail: "dev@stainless.com",\n\t\tRequest: "request",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'auth whoami', + method: 'login email', example: - "beeper-desktop-cli matrix:bridges:auth whoami \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop-cli app:login email \\\n --access-token 'My Access Token' \\\n --email dev@stainless.com \\\n --request request", }, php: { - method: 'matrix->bridges->auth->whoami', + method: 'app->login->email', example: - "matrix->bridges->auth->whoami('bridgeID');\n\nvar_dump($response);", + "app->login->email(\n email: 'dev@stainless.com', request: 'request'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/whoami \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/email \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "email": "dev@stainless.com",\n "request": "request"\n }\'', }, }, }, { - name: 'list_flows', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows', - httpMethod: 'get', - summary: 'Get the available login flows.', - description: 'Get the available login flows.', - stainlessPath: '(resource) matrix.bridges.auth > (method) list_flows', - qualified: 'client.matrix.bridges.auth.listFlows', - params: ['bridgeID: string;'], - response: '{ flows?: { id: string; description: string; name: string; }[]; }', + name: 'response', + endpoint: '/v1/app/login/response', + httpMethod: 'post', + summary: 'Complete login with code', + description: + 'Finish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.', + stainlessPath: '(resource) app.login > (method) response', + qualified: 'client.app.login.response', + params: ['request: string;', 'response: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }", markdown: - "## list_flows\n\n`client.matrix.bridges.auth.listFlows(bridgeID: string): { flows?: object[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows`\n\nGet the available login flows.\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ flows?: { id: string; description: string; name: string; }[]; }`\n\n - `flows?: { id: string; description: string; name: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.listFlows('bridgeID');\n\nconsole.log(response);\n```", + "## response\n\n`client.app.login.response(request: string, response: string): { appState: object; desktopAPI: object; matrix: object; } | { copy: object; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n**post** `/v1/app/login/response`\n\nFinish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.\n\n### Parameters\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `response: string`\n Sign-in code from the user email.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.listFlows', + method: 'client.app.login.response', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.listFlows('bridgeID');\n\nconsole.log(response.flows);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);", }, python: { - method: 'matrix.bridges.auth.list_flows', + method: 'app.login.response', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.list_flows(\n "bridgeID",\n)\nprint(response.flows)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.response(\n request="request",\n response="response",\n)\nprint(response)', }, go: { - method: 'client.Matrix.Bridges.Auth.ListFlows', + method: 'client.App.Login.Response', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.ListFlows(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Flows)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Response(context.TODO(), beeperdesktopapi.AppLoginResponseParams{\n\t\tRequest: "request",\n\t\tResponse: "response",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'auth list_flows', + method: 'login response', example: - "beeper-desktop-cli matrix:bridges:auth list-flows \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop-cli app:login response \\\n --access-token 'My Access Token' \\\n --request request \\\n --response response", }, php: { - method: 'matrix->bridges->auth->listFlows', + method: 'app->login->response', example: - "matrix->bridges->auth->listFlows('bridgeID');\n\nvar_dump($response);", + "app->login->response(\n request: 'request', response: 'response'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/flows \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/response \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "request": "request",\n "response": "response"\n }\'', }, }, }, { - name: 'list_logins', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins', - httpMethod: 'get', - summary: 'Get the login IDs of the current user.', - description: 'Get the login IDs of the current user.', - stainlessPath: '(resource) matrix.bridges.auth > (method) list_logins', - qualified: 'client.matrix.bridges.auth.listLogins', - params: ['bridgeID: string;'], - response: '{ login_ids?: string[]; }', + name: 'register', + endpoint: '/v1/app/login/register', + httpMethod: 'post', + summary: 'Create account', + description: 'Create a Beeper account after the user chooses a username and accepts the Terms of Use.', + stainlessPath: '(resource) app.login > (method) register', + qualified: 'client.app.login.register', + params: ['acceptTerms: true;', 'leadToken: string;', 'request: string;', 'username: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; }", markdown: - "## list_logins\n\n`client.matrix.bridges.auth.listLogins(bridgeID: string): { login_ids?: string[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins`\n\nGet the login IDs of the current user.\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ login_ids?: string[]; }`\n\n - `login_ids?: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.listLogins('bridgeID');\n\nconsole.log(response);\n```", + "## register\n\n`client.app.login.register(acceptTerms: true, leadToken: string, request: string, username: string): { appState: object; desktopAPI: object; matrix: object; }`\n\n**post** `/v1/app/login/register`\n\nCreate a Beeper account after the user chooses a username and accepts the Terms of Use.\n\n### Parameters\n\n- `acceptTerms: true`\n Confirms that the user accepted the Terms of Use and acknowledged the Privacy Policy.\n\n- `leadToken: string`\n Registration token returned by Beeper.\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `username: string`\n Username selected by the user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }`\n - `matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.listLogins', + method: 'client.app.login.register', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.listLogins('bridgeID');\n\nconsole.log(response.login_ids);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.auth.list_logins', + method: 'app.login.register', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.list_logins(\n "bridgeID",\n)\nprint(response.login_ids)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.register(\n accept_terms=True,\n lead_token="leadToken",\n request="request",\n username="x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Auth.ListLogins', + method: 'client.App.Login.Register', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.ListLogins(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.LoginIDs)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Register(context.TODO(), beeperdesktopapi.AppLoginRegisterParams{\n\t\tAcceptTerms: true,\n\t\tLeadToken: "leadToken",\n\t\tRequest: "request",\n\t\tUsername: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'auth list_logins', + method: 'login register', example: - "beeper-desktop-cli matrix:bridges:auth list-logins \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop-cli app:login register \\\n --access-token 'My Access Token' \\\n --accept-terms true \\\n --lead-token leadToken \\\n --request request \\\n --username x", }, php: { - method: 'matrix->bridges->auth->listLogins', + method: 'app->login->register', example: - "matrix->bridges->auth->listLogins('bridgeID');\n\nvar_dump($response);", + "app->login->register(\n acceptTerms: true, leadToken: 'leadToken', request: 'request', username: 'x'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/logins \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/register \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "acceptTerms": true,\n "leadToken": "leadToken",\n "request": "request",\n "username": "x"\n }\'', }, }, }, { - name: 'start_login', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}', + name: 'verify', + endpoint: '/v1/app/e2ee/recovery-code/verify', httpMethod: 'post', - summary: 'Start a new login process.', - description: - "This endpoint starts a new login process, which is used to log into the bridge.\n\nThe basic flow of the entire login, including calling this endpoint, is:\n1. Call `GET /v3/login/flows` to get the list of available flows.\n If there's more than one flow, ask the user to pick which one they want to use.\n2. Call this endpoint with the chosen flow ID to start the login.\n The first login step will be returned.\n3. Render the information provided in the step.\n4. Call the `/login/step/...` endpoint corresponding to the step type:\n * For `user_input` and `cookies`, acquire the requested fields before calling the endpoint.\n * For `display_and_wait`, call the endpoint immediately\n (as there's nothing to acquire on the client side).\n5. Handle the data returned by the login step endpoint:\n * If an error is returned, the login has failed and must be restarted\n (from either step 1 or step 2) if the user wants to try again.\n * If step type `complete` is returned, the login finished successfully.\n * Otherwise, go to step 3 with the new data.\n", - stainlessPath: '(resource) matrix.bridges.auth > (method) start_login', - qualified: 'client.matrix.bridges.auth.startLogin', - params: ['bridgeID: string;', 'flowID: string;', 'login_id?: string;'], + summary: 'Verify with recovery key', + description: 'Unlock encrypted messages with the user recovery key.', + stainlessPath: '(resource) app.e2ee.recovery_code > (method) verify', + qualified: 'client.app.e2ee.recoveryCode.verify', + params: ['recoveryCode: string;'], response: - "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## start_login\n\n`client.matrix.bridges.auth.startLogin(bridgeID: string, flowID: string, login_id?: string): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}`\n\nThis endpoint starts a new login process, which is used to log into the bridge.\n\nThe basic flow of the entire login, including calling this endpoint, is:\n1. Call `GET /v3/login/flows` to get the list of available flows.\n If there's more than one flow, ask the user to pick which one they want to use.\n2. Call this endpoint with the chosen flow ID to start the login.\n The first login step will be returned.\n3. Render the information provided in the step.\n4. Call the `/login/step/...` endpoint corresponding to the step type:\n * For `user_input` and `cookies`, acquire the requested fields before calling the endpoint.\n * For `display_and_wait`, call the endpoint immediately\n (as there's nothing to acquire on the client side).\n5. Handle the data returned by the login step endpoint:\n * If an error is returned, the login has failed and must be restarted\n (from either step 1 or step 2) if the user wants to try again.\n * If step type `complete` is returned, the login finished successfully.\n * Otherwise, go to step 3 with the new data.\n\n\n### Parameters\n\n- `bridgeID: string`\n\n- `flowID: string`\n\n- `login_id?: string`\n An existing login ID to re-login as. If this is specified and the user logs into a different account, the provided ID will be logged out.\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## verify\n\n`client.app.e2ee.recoveryCode.verify(recoveryCode: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/verify`\n\nUnlock encrypted messages with the user recovery key.\n\n### Parameters\n\n- `recoveryCode: string`\n Recovery key saved by the user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.startLogin', + method: 'client.app.e2ee.recoveryCode.verify', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' });\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' });\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.auth.start_login', + method: 'app.e2ee.recovery_code.verify', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.start_login(\n flow_id="qr",\n bridge_id="bridgeID",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.verify(\n recovery_code="x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Auth.StartLogin', + method: 'client.App.E2ee.RecoveryCode.Verify', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.StartLogin(\n\t\tcontext.TODO(),\n\t\t"qr",\n\t\tbeeperdesktopapi.MatrixBridgeAuthStartLoginParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.Verify(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeVerifyParams{\n\t\tRecoveryCode: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'auth start_login', + method: 'recovery_code verify', example: - "beeper-desktop-cli matrix:bridges:auth start-login \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --flow-id qr", + "beeper-desktop-cli app:e2ee:recovery-code verify \\\n --access-token 'My Access Token' \\\n --recovery-code x", }, php: { - method: 'matrix->bridges->auth->startLogin', + method: 'app->e2ee->recoveryCode->verify', example: - "matrix->bridges->auth->startLogin(\n 'qr', bridgeID: 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496'\n);\n\nvar_dump($response);", + "app->e2ee->recoveryCode->verify(recoveryCode: 'x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/start/$FLOW_ID \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/recovery-code/verify \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryCode": "x"\n }\'', }, }, }, { - name: 'submit_user_input', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input', + name: 'mark_backed_up', + endpoint: '/v1/app/e2ee/recovery-code/mark-backed-up', httpMethod: 'post', - summary: 'Submit user input in a login process.', - description: 'Submit user input in a login process.', - stainlessPath: '(resource) matrix.bridges.auth > (method) submit_user_input', - qualified: 'client.matrix.bridges.auth.submitUserInput', - params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;', 'body: object;'], + summary: 'Mark recovery key as saved', + description: 'Record that the user saved their recovery key.', + stainlessPath: '(resource) app.e2ee.recovery_code > (method) mark_backed_up', + qualified: 'client.app.e2ee.recoveryCode.markBackedUp', response: - "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## submit_user_input\n\n`client.matrix.bridges.auth.submitUserInput(bridgeID: string, loginProcessID: string, stepID: string, body: object): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input`\n\nSubmit user input in a login process.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n- `body: object`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.submitUserInput('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);\n```", + "## mark_backed_up\n\n`client.app.e2ee.recoveryCode.markBackedUp(): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/mark-backed-up`\n\nRecord that the user saved their recovery key.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.markBackedUp();\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.submitUserInput', + method: 'client.app.e2ee.recoveryCode.markBackedUp', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.submitUserInput('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.markBackedUp();\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.auth.submit_user_input', + method: 'app.e2ee.recovery_code.mark_backed_up', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.submit_user_input(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n body={\n "foo": "string"\n },\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.mark_backed_up()\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Auth.SubmitUserInput', + method: 'client.App.E2ee.RecoveryCode.MarkBackedUp', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.SubmitUserInput(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthSubmitUserInputParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t\tBody: map[string]string{\n\t\t\t\t"foo": "string",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.MarkBackedUp(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'auth submit_user_input', + method: 'recovery_code mark_backed_up', example: - "beeper-desktop-cli matrix:bridges:auth submit-user-input \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID \\\n --body '{foo: string}'", + "beeper-desktop-cli app:e2ee:recovery-code mark-backed-up \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->bridges->auth->submitUserInput', + method: 'app->e2ee->recoveryCode->markBackedUp', example: - "matrix->bridges->auth->submitUserInput(\n 'stepID',\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: ['foo' => 'string'],\n);\n\nvar_dump($response);", + "app->e2ee->recoveryCode->markBackedUp();\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/user_input \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "foo": "string"\n }\'', + 'curl http://localhost:23373/v1/app/e2ee/recovery-code/mark-backed-up \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'submit_cookies', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies', + name: 'create', + endpoint: '/v1/app/e2ee/recovery-code/reset', httpMethod: 'post', - summary: 'Submit extracted cookies in a login process.', - description: 'Submit extracted cookies in a login process.', - stainlessPath: '(resource) matrix.bridges.auth > (method) submit_cookies', - qualified: 'client.matrix.bridges.auth.submitCookies', - params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;', 'body: object;'], + summary: 'Create new recovery key', + description: 'Create a new recovery key when the user cannot use the existing one.', + stainlessPath: '(resource) app.e2ee.recovery_code.reset > (method) create', + qualified: 'client.app.e2ee.recoveryCode.reset.create', + params: ['recoveryCode?: string;'], response: - "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; recoveryCode: string; }", markdown: - "## submit_cookies\n\n`client.matrix.bridges.auth.submitCookies(bridgeID: string, loginProcessID: string, stepID: string, body: object): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies`\n\nSubmit extracted cookies in a login process.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n- `body: object`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.submitCookies('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);\n```", + "## create\n\n`client.app.e2ee.recoveryCode.reset.create(recoveryCode?: string): { appState: object; recoveryCode: string; }`\n\n**post** `/v1/app/e2ee/recovery-code/reset`\n\nCreate a new recovery key when the user cannot use the existing one.\n\n### Parameters\n\n- `recoveryCode?: string`\n Existing recovery key, if the user has it.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; recoveryCode: string; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `recoveryCode: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reset = await client.app.e2ee.recoveryCode.reset.create();\n\nconsole.log(reset);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.submitCookies', + method: 'client.app.e2ee.recoveryCode.reset.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.submitCookies('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reset = await client.app.e2ee.recoveryCode.reset.create();\n\nconsole.log(reset.appState);", }, python: { - method: 'matrix.bridges.auth.submit_cookies', + method: 'app.e2ee.recovery_code.reset.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.submit_cookies(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n body={\n "foo": "string"\n },\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreset = client.app.e2ee.recovery_code.reset.create()\nprint(reset.app_state)', }, go: { - method: 'client.Matrix.Bridges.Auth.SubmitCookies', + method: 'client.App.E2ee.RecoveryCode.Reset.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.SubmitCookies(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthSubmitCookiesParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t\tBody: map[string]string{\n\t\t\t\t"foo": "string",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treset, err := client.App.E2ee.RecoveryCode.Reset.New(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeResetNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reset.AppState)\n}\n', }, cli: { - method: 'auth submit_cookies', + method: 'reset create', example: - "beeper-desktop-cli matrix:bridges:auth submit-cookies \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID \\\n --body '{foo: string}'", + "beeper-desktop-cli app:e2ee:recovery-code:reset create \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->bridges->auth->submitCookies', + method: 'app->e2ee->recoveryCode->reset->create', example: - "matrix->bridges->auth->submitCookies(\n 'stepID',\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: ['foo' => 'string'],\n);\n\nvar_dump($response);", + "app->e2ee->recoveryCode->reset->create(\n recoveryCode: 'recoveryCode'\n);\n\nvar_dump($reset);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/cookies \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "foo": "string"\n }\'', + 'curl http://localhost:23373/v1/app/e2ee/recovery-code/reset \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'wait_for_step', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait', + name: 'confirm', + endpoint: '/v1/app/e2ee/recovery-code/reset/confirm', httpMethod: 'post', - summary: 'Wait for the next step after displaying data to the user.', - description: 'Wait for the next step after displaying data to the user.', - stainlessPath: '(resource) matrix.bridges.auth > (method) wait_for_step', - qualified: 'client.matrix.bridges.auth.waitForStep', - params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;'], + summary: 'Confirm new recovery key', + description: 'Confirm that the new recovery key should be used for this account.', + stainlessPath: '(resource) app.e2ee.recovery_code.reset > (method) confirm', + qualified: 'client.app.e2ee.recoveryCode.reset.confirm', + params: ['recoveryCode: string;'], response: - "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## wait_for_step\n\n`client.matrix.bridges.auth.waitForStep(bridgeID: string, loginProcessID: string, stepID: string): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait`\n\nWait for the next step after displaying data to the user.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.waitForStep('stepID', { bridgeID: 'bridgeID', loginProcessID: 'loginProcessID' });\n\nconsole.log(response);\n```", + "## confirm\n\n`client.app.e2ee.recoveryCode.reset.confirm(recoveryCode: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/reset/confirm`\n\nConfirm that the new recovery key should be used for this account.\n\n### Parameters\n\n- `recoveryCode: string`\n New recovery key returned by the reset step.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.waitForStep', + method: 'client.app.e2ee.recoveryCode.reset.confirm', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.waitForStep('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' });\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.auth.wait_for_step', + method: 'app.e2ee.recovery_code.reset.confirm', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.wait_for_step(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.reset.confirm(\n recovery_code="x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Auth.WaitForStep', + method: 'client.App.E2ee.RecoveryCode.Reset.Confirm', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.WaitForStep(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthWaitForStepParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.Reset.Confirm(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeResetConfirmParams{\n\t\tRecoveryCode: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'auth wait_for_step', + method: 'reset confirm', example: - "beeper-desktop-cli matrix:bridges:auth wait-for-step \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID", + "beeper-desktop-cli app:e2ee:recovery-code:reset confirm \\\n --access-token 'My Access Token' \\\n --recovery-code x", }, php: { - method: 'matrix->bridges->auth->waitForStep', + method: 'app->e2ee->recoveryCode->reset->confirm', example: - "matrix->bridges->auth->waitForStep(\n 'stepID', bridgeID: 'bridgeID', loginProcessID: 'loginProcessID'\n);\n\nvar_dump($response);", + "app->e2ee->recoveryCode->reset->confirm(recoveryCode: 'x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/display_and_wait \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/recovery-code/reset/confirm \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryCode": "x"\n }\'', }, }, }, { - name: 'logout', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}', + name: 'create', + endpoint: '/v1/app/e2ee/verification', httpMethod: 'post', - summary: 'Log out of an existing login.', - description: 'Log out of an existing login.', - stainlessPath: '(resource) matrix.bridges.auth > (method) logout', - qualified: 'client.matrix.bridges.auth.logout', - params: ['bridgeID: string;', 'loginID: string;'], - response: 'object', + summary: 'Start device verification', + description: 'Start verifying this device from another signed-in device.', + stainlessPath: '(resource) app.e2ee.verification > (method) create', + qualified: 'client.app.e2ee.verification.create', + params: ['userID?: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; verificationID: string; }", markdown: - "## logout\n\n`client.matrix.bridges.auth.logout(bridgeID: string, loginID: string): object`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}`\n\nLog out of an existing login.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginID: string`\n The unique ID of a login. Defined by the network connector.\n\n### Returns\n\n- `object`\n Empty object\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## create\n\n`client.app.e2ee.verification.create(userID?: string): { appState: object; verificationID: string; }`\n\n**post** `/v1/app/e2ee/verification`\n\nStart verifying this device from another signed-in device.\n\n### Parameters\n\n- `userID?: string`\n User ID to verify. Defaults to the signed-in user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; verificationID: string; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `verificationID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.e2ee.verification.create();\n\nconsole.log(verification);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.logout', + method: 'client.app.e2ee.verification.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', {\n bridgeID: 'bridgeID',\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.e2ee.verification.create();\n\nconsole.log(verification.appState);", }, python: { - method: 'matrix.bridges.auth.logout', + method: 'app.e2ee.verification.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.logout(\n login_id="bcc68892-b180-414f-9516-b4aadf7d0496",\n bridge_id="bridgeID",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.e2ee.verification.create()\nprint(verification.app_state)', }, go: { - method: 'client.Matrix.Bridges.Auth.Logout', + method: 'client.App.E2ee.Verification.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.Logout(\n\t\tcontext.TODO(),\n\t\t"bcc68892-b180-414f-9516-b4aadf7d0496",\n\t\tbeeperdesktopapi.MatrixBridgeAuthLogoutParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.E2ee.Verification.New(context.TODO(), beeperdesktopapi.AppE2eeVerificationNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.AppState)\n}\n', }, cli: { - method: 'auth logout', - example: - "beeper-desktop-cli matrix:bridges:auth logout \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-id bcc68892-b180-414f-9516-b4aadf7d0496", + method: 'verification create', + example: "beeper-desktop-cli app:e2ee:verification create \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->bridges->auth->logout', + method: 'app->e2ee->verification->create', example: - "matrix->bridges->auth->logout(\n 'bcc68892-b180-414f-9516-b4aadf7d0496', bridgeID: 'bridgeID'\n);\n\nvar_dump($response);", + "app->e2ee->verification->create(userID: 'userID');\n\nvar_dump($verification);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/logout/$LOGIN_ID \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/verification \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'list', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts', - httpMethod: 'get', - summary: 'Get a list of contacts.', - description: 'Get a list of contacts.', - stainlessPath: '(resource) matrix.bridges.contacts > (method) list', - qualified: 'client.matrix.bridges.contacts.list', - params: ['bridgeID: string;', 'login_id?: string;'], + name: 'accept', + endpoint: '/v1/app/e2ee/verification/{verificationID}/accept', + httpMethod: 'post', + summary: 'Accept device verification', + description: 'Accept an incoming device verification request.', + stainlessPath: '(resource) app.e2ee.verification > (method) accept', + qualified: 'client.app.e2ee.verification.accept', + params: ['verificationID: string;'], response: - '{ contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }', + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## list\n\n`client.matrix.bridges.contacts.list(bridgeID: string, login_id?: string): { contacts?: object[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts`\n\nGet a list of contacts.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }`\n\n - `contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst contacts = await client.matrix.bridges.contacts.list('bridgeID');\n\nconsole.log(contacts);\n```", + "## accept\n\n`client.app.e2ee.verification.accept(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/accept`\n\nAccept an incoming device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.accept('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.contacts.list', + method: 'client.app.e2ee.verification.accept', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst contacts = await client.matrix.bridges.contacts.list('bridgeID');\n\nconsole.log(contacts.contacts);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.accept('x');\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.contacts.list', + method: 'app.e2ee.verification.accept', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\ncontacts = client.matrix.bridges.contacts.list(\n bridge_id="bridgeID",\n)\nprint(contacts.contacts)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.accept(\n "x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Contacts.List', + method: 'client.App.E2ee.Verification.Accept', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tcontacts, err := client.Matrix.Bridges.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"bridgeID",\n\t\tbeeperdesktopapi.MatrixBridgeContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", contacts.Contacts)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Accept(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'contacts list', + method: 'verification accept', example: - "beeper-desktop-cli matrix:bridges:contacts list \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop-cli app:e2ee:verification accept \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->contacts->list', + method: 'app->e2ee->verification->accept', example: - "matrix->bridges->contacts->list(\n 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496'\n);\n\nvar_dump($contacts);", + "app->e2ee->verification->accept('x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/contacts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/accept \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'search', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users', + name: 'cancel', + endpoint: '/v1/app/e2ee/verification/{verificationID}/cancel', httpMethod: 'post', - summary: 'Search for users on the remote network', - description: 'Search for users on the remote network', - stainlessPath: '(resource) matrix.bridges.users > (method) search', - qualified: 'client.matrix.bridges.users.search', - params: ['bridgeID: string;', 'login_id?: string;', 'query?: string;'], + summary: 'Cancel device verification', + description: 'Cancel an active device verification request.', + stainlessPath: '(resource) app.e2ee.verification > (method) cancel', + qualified: 'client.app.e2ee.verification.cancel', + params: ['verificationID: string;', 'code?: string;', 'reason?: string;'], response: - '{ results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }', + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## search\n\n`client.matrix.bridges.users.search(bridgeID: string, login_id?: string, query?: string): { results?: object[]; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users`\n\nSearch for users on the remote network\n\n### Parameters\n\n- `bridgeID: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n- `query?: string`\n The search query to send to the remote network\n\n### Returns\n\n- `{ results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }`\n\n - `results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.users.search('bridgeID');\n\nconsole.log(response);\n```", + "## cancel\n\n`client.app.e2ee.verification.cancel(verificationID: string, code?: string, reason?: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/cancel`\n\nCancel an active device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n- `code?: string`\n Optional cancellation code.\n\n- `reason?: string`\n Optional user-facing cancellation reason.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.cancel('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.users.search', + method: 'client.app.e2ee.verification.cancel', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.users.search('bridgeID');\n\nconsole.log(response.results);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.cancel('x');\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.users.search', + method: 'app.e2ee.verification.cancel', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.users.search(\n bridge_id="bridgeID",\n)\nprint(response.results)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.cancel(\n verification_id="x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Users.Search', + method: 'client.App.E2ee.Verification.Cancel', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Users.Search(\n\t\tcontext.TODO(),\n\t\t"bridgeID",\n\t\tbeeperdesktopapi.MatrixBridgeUserSearchParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Results)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Cancel(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.AppE2eeVerificationCancelParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'users search', + method: 'verification cancel', example: - "beeper-desktop-cli matrix:bridges:users search \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop-cli app:e2ee:verification cancel \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->users->search', + method: 'app->e2ee->verification->cancel', example: - "matrix->bridges->users->search(\n 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496', query: 'query'\n);\n\nvar_dump($response);", + "app->e2ee->verification->cancel(\n 'x', code: 'code', reason: 'reason'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/search_users \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/cancel \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'resolve', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}', - httpMethod: 'get', - summary: 'Resolve an identifier to a user on the remote network.', - description: 'Resolve an identifier to a user on the remote network.', - stainlessPath: '(resource) matrix.bridges.users > (method) resolve', - qualified: 'client.matrix.bridges.users.resolve', - params: ['bridgeID: string;', 'identifier: string;', 'login_id?: string;'], + name: 'scan', + endpoint: '/v1/app/e2ee/verification/qr/scan', + httpMethod: 'post', + summary: 'Scan verification QR code', + description: 'Submit the QR code scanned from another signed-in device.', + stainlessPath: '(resource) app.e2ee.verification.qr > (method) scan', + qualified: 'client.app.e2ee.verification.qr.scan', + params: ['data: string;'], response: - '{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }', + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## resolve\n\n`client.matrix.bridges.users.resolve(bridgeID: string, identifier: string, login_id?: string): { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}`\n\nResolve an identifier to a user on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `identifier: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n A successfully resolved identifier.\n\n - `id: string`\n - `avatar_url?: string`\n - `dm_room_mxid?: string`\n - `identifiers?: string[]`\n - `mxid?: string`\n - `name?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## scan\n\n`client.app.e2ee.verification.qr.scan(data: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/qr/scan`\n\nSubmit the QR code scanned from another signed-in device.\n\n### Parameters\n\n- `data: string`\n QR code payload scanned from the other device.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.qr.scan({ data: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.users.resolve', + method: 'client.app.e2ee.verification.qr.scan', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.qr.scan({ data: 'x' });\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.users.resolve', + method: 'app.e2ee.verification.qr.scan', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.users.resolve(\n identifier="identifier",\n bridge_id="bridgeID",\n)\nprint(response.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.qr.scan(\n data="x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Users.Resolve', + method: 'client.App.E2ee.Verification.Qr.Scan', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Users.Resolve(\n\t\tcontext.TODO(),\n\t\t"identifier",\n\t\tbeeperdesktopapi.MatrixBridgeUserResolveParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Qr.Scan(context.TODO(), beeperdesktopapi.AppE2eeVerificationQrScanParams{\n\t\tData: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'users resolve', + method: 'qr scan', example: - "beeper-desktop-cli matrix:bridges:users resolve \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --identifier identifier", + "beeper-desktop-cli app:e2ee:verification:qr scan \\\n --access-token 'My Access Token' \\\n --data x", }, php: { - method: 'matrix->bridges->users->resolve', + method: 'app->e2ee->verification->qr->scan', example: - "matrix->bridges->users->resolve(\n 'identifier',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n);\n\nvar_dump($response);", + "app->e2ee->verification->qr->scan(data: 'x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/resolve_identifier/$IDENTIFIER \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/verification/qr/scan \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "data": "x"\n }\'', }, }, }, { - name: 'create_dm', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}', + name: 'confirm_scanned', + endpoint: '/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned', httpMethod: 'post', - summary: 'Create a direct chat with a user on the remote network.', - description: 'Create a direct chat with a user on the remote network.', - stainlessPath: '(resource) matrix.bridges.rooms > (method) create_dm', - qualified: 'client.matrix.bridges.rooms.createDm', - params: ['bridgeID: string;', 'identifier: string;', 'login_id?: string;'], + summary: 'Confirm QR code scan', + description: 'Confirm that another device scanned this device QR code.', + stainlessPath: '(resource) app.e2ee.verification.qr > (method) confirm_scanned', + qualified: 'client.app.e2ee.verification.qr.confirmScanned', + params: ['verificationID: string;'], response: - '{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }', + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## create_dm\n\n`client.matrix.bridges.rooms.createDm(bridgeID: string, identifier: string, login_id?: string): { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}`\n\nCreate a direct chat with a user on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `identifier: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n A successfully resolved identifier.\n\n - `id: string`\n - `avatar_url?: string`\n - `dm_room_mxid?: string`\n - `identifiers?: string[]`\n - `mxid?: string`\n - `name?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## confirm_scanned\n\n`client.app.e2ee.verification.qr.confirmScanned(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned`\n\nConfirm that another device scanned this device QR code.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.qr.confirmScanned('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.rooms.createDm', + method: 'client.app.e2ee.verification.qr.confirmScanned', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.qr.confirmScanned('x');\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.rooms.create_dm', + method: 'app.e2ee.verification.qr.confirm_scanned', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.rooms.create_dm(\n identifier="identifier",\n bridge_id="bridgeID",\n)\nprint(response.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.qr.confirm_scanned(\n "x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Rooms.NewDm', + method: 'client.App.E2ee.Verification.Qr.ConfirmScanned', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Rooms.NewDm(\n\t\tcontext.TODO(),\n\t\t"identifier",\n\t\tbeeperdesktopapi.MatrixBridgeRoomNewDmParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Qr.ConfirmScanned(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'rooms create_dm', + method: 'qr confirm_scanned', example: - "beeper-desktop-cli matrix:bridges:rooms create-dm \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --identifier identifier", + "beeper-desktop-cli app:e2ee:verification:qr confirm-scanned \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->rooms->createDm', + method: 'app->e2ee->verification->qr->confirmScanned', example: - "matrix->bridges->rooms->createDm(\n 'identifier',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n);\n\nvar_dump($response);", + "app->e2ee->verification->qr->confirmScanned('x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/create_dm/$IDENTIFIER \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/qr/confirm-scanned \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'create_group', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}', + name: 'start', + endpoint: '/v1/app/e2ee/verification/{verificationID}/sas/start', httpMethod: 'post', - summary: 'Create a group chat on the remote network.', - description: 'Create a group chat on the remote network.', - stainlessPath: '(resource) matrix.bridges.rooms > (method) create_group', - qualified: 'client.matrix.bridges.rooms.createGroup', - params: [ - 'bridgeID: string;', - 'groupType: string;', - 'login_id?: string;', - 'avatar?: { url?: string; };', - 'disappear?: { timer?: number; type?: string; };', - 'name?: { name?: string; };', - 'parent?: object;', - 'participants?: string[];', - 'room_id?: string;', - 'topic?: { topic?: string; };', - 'type?: string;', - 'username?: string;', - ], - response: '{ id: string; mxid: string; }', + summary: 'Start emoji verification', + description: 'Start emoji comparison for device verification.', + stainlessPath: '(resource) app.e2ee.verification.sas > (method) start', + qualified: 'client.app.e2ee.verification.sas.start', + params: ['verificationID: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## create_group\n\n`client.matrix.bridges.rooms.createGroup(bridgeID: string, groupType: string, login_id?: string, avatar?: { url?: string; }, disappear?: { timer?: number; type?: string; }, name?: { name?: string; }, parent?: object, participants?: string[], room_id?: string, topic?: { topic?: string; }, type?: string, username?: string): { id: string; mxid: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}`\n\nCreate a group chat on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `groupType: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n- `avatar?: { url?: string; }`\n The `m.room.avatar` event content for the room.\n - `url?: string`\n\n- `disappear?: { timer?: number; type?: string; }`\n The `com.beeper.disappearing_timer` event content for the room.\n - `timer?: number`\n - `type?: string`\n\n- `name?: { name?: string; }`\n The `m.room.name` event content for the room.\n - `name?: string`\n\n- `parent?: object`\n\n- `participants?: string[]`\n The users to add to the group initially.\n\n- `room_id?: string`\n An existing Matrix room ID to bridge to.\nThe other parameters must be already in sync with the room state when using this parameter.\n\n\n- `topic?: { topic?: string; }`\n The `m.room.topic` event content for the room.\n - `topic?: string`\n\n- `type?: string`\n The type of group to create.\n\n- `username?: string`\n The public username for the created group.\n\n### Returns\n\n- `{ id: string; mxid: string; }`\n A successfully created group chat.\n\n - `id: string`\n - `mxid: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.rooms.createGroup('groupType', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## start\n\n`client.app.e2ee.verification.sas.start(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/sas/start`\n\nStart emoji comparison for device verification.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.sas.start('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.rooms.createGroup', + method: 'client.app.e2ee.verification.sas.start', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.rooms.createGroup('groupType', {\n bridgeID: 'bridgeID',\n});\n\nconsole.log(response.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.sas.start('x');\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.rooms.create_group', + method: 'app.e2ee.verification.sas.start', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.rooms.create_group(\n group_type="groupType",\n bridge_id="bridgeID",\n)\nprint(response.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.sas.start(\n "x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Rooms.NewGroup', + method: 'client.App.E2ee.Verification.Sas.Start', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Rooms.NewGroup(\n\t\tcontext.TODO(),\n\t\t"groupType",\n\t\tbeeperdesktopapi.MatrixBridgeRoomNewGroupParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Sas.Start(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'rooms create_group', + method: 'sas start', example: - "beeper-desktop-cli matrix:bridges:rooms create-group \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --group-type groupType", + "beeper-desktop-cli app:e2ee:verification:sas start \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->rooms->createGroup', + method: 'app->e2ee->verification->sas->start', example: - "matrix->bridges->rooms->createGroup(\n 'groupType',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n avatar: ['url' => 'url'],\n disappear: ['timer' => 0, 'type' => 'type'],\n name: ['name' => 'name'],\n parent: (object) [],\n participants: ['string'],\n roomID: 'room_id',\n topic: ['topic' => 'topic'],\n type: 'channel',\n username: 'username',\n);\n\nvar_dump($response);", + "app->e2ee->verification->sas->start('x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/create_group/$GROUP_TYPE \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/sas/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities', - httpMethod: 'get', - summary: 'Get bridge capabilities', - description: 'Get bridge capabilities', - stainlessPath: '(resource) matrix.bridges.capabilities > (method) retrieve', - qualified: 'client.matrix.bridges.capabilities.retrieve', - params: ['bridgeID: string;'], - response: 'object', + name: 'confirm', + endpoint: '/v1/app/e2ee/verification/{verificationID}/sas/confirm', + httpMethod: 'post', + summary: 'Confirm emoji verification', + description: 'Confirm that the emoji or number sequence matches on both devices.', + stainlessPath: '(resource) app.e2ee.verification.sas > (method) confirm', + qualified: 'client.app.e2ee.verification.sas.confirm', + params: ['verificationID: string;'], + response: + "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", markdown: - "## retrieve\n\n`client.matrix.bridges.capabilities.retrieve(bridgeID: string): object`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities`\n\nGet bridge capabilities\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst capability = await client.matrix.bridges.capabilities.retrieve('bridgeID');\n\nconsole.log(capability);\n```", + "## confirm\n\n`client.app.e2ee.verification.sas.confirm(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/sas/confirm`\n\nConfirm that the emoji or number sequence matches on both devices.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.sas.confirm('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.capabilities.retrieve', + method: 'client.app.e2ee.verification.sas.confirm', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst capability = await client.matrix.bridges.capabilities.retrieve('bridgeID');\n\nconsole.log(capability);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.sas.confirm('x');\n\nconsole.log(response.appState);", }, python: { - method: 'matrix.bridges.capabilities.retrieve', + method: 'app.e2ee.verification.sas.confirm', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\ncapability = client.matrix.bridges.capabilities.retrieve(\n "bridgeID",\n)\nprint(capability)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.sas.confirm(\n "x",\n)\nprint(response.app_state)', }, go: { - method: 'client.Matrix.Bridges.Capabilities.Get', + method: 'client.App.E2ee.Verification.Sas.Confirm', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tcapability, err := client.Matrix.Bridges.Capabilities.Get(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", capability)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Sas.Confirm(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', }, cli: { - method: 'capabilities retrieve', + method: 'sas confirm', example: - "beeper-desktop-cli matrix:bridges:capabilities retrieve \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop-cli app:e2ee:verification:sas confirm \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->capabilities->retrieve', + method: 'app->e2ee->verification->sas->confirm', example: - "matrix->bridges->capabilities->retrieve('bridgeID');\n\nvar_dump($capability);", + "app->e2ee->verification->sas->confirm('x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/capabilities \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/sas/confirm \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve', - endpoint: '/v1/chats/{chatID}', + name: 'retrieve_profile', + endpoint: '/_matrix/client/v3/profile/{userId}', httpMethod: 'get', - summary: 'Retrieve chat details', - description: 'Retrieve chat details including metadata, participants, and latest message', - stainlessPath: '(resource) chats > (method) retrieve', - qualified: 'client.chats.retrieve', - params: ['chatID: string;', 'maxParticipantCount?: number;'], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + summary: 'Get all profile information for a user.', + description: 'Get the complete profile for a user.', + stainlessPath: '(resource) matrix.users > (method) retrieve_profile', + qualified: 'client.matrix.users.retrieveProfile', + params: ['userId: string;'], + response: '{ avatar_url?: string; displayname?: string; m.tz?: string; }', markdown: - "## retrieve\n\n`client.chats.retrieve(chatID: string, maxParticipantCount?: number): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/{chatID}`\n\nRetrieve chat details including metadata, participants, and latest message\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `maxParticipantCount?: number`\n 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.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## retrieve_profile\n\n`client.matrix.users.retrieveProfile(userId: string): { avatar_url?: string; displayname?: string; m.tz?: string; }`\n\n**get** `/_matrix/client/v3/profile/{userId}`\n\nGet the complete profile for a user.\n\n### Parameters\n\n- `userId: string`\n\n### Returns\n\n- `{ avatar_url?: string; displayname?: string; m.tz?: string; }`\n\n - `avatar_url?: string`\n - `displayname?: string`\n - `m.tz?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.users.retrieveProfile('@alice:example.com');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.chats.retrieve', + method: 'client.matrix.users.retrieveProfile', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.users.retrieveProfile('@alice:example.com');\n\nconsole.log(response.avatar_url);", }, python: { - method: 'chats.retrieve', + method: 'matrix.users.retrieve_profile', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.retrieve(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.users.retrieve_profile(\n "@alice:example.com",\n)\nprint(response.avatar_url)', }, go: { - method: 'client.Chats.Get', + method: 'client.Matrix.Users.GetProfile', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Get(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatGetParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Users.GetProfile(context.TODO(), "@alice:example.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AvatarURL)\n}\n', }, cli: { - method: 'chats retrieve', + method: 'users retrieve_profile', example: - "beeper-desktop-cli chats retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:users retrieve-profile \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com", }, php: { - method: 'chats->retrieve', + method: 'matrix->users->retrieveProfile', example: - "chats->retrieve(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', maxParticipantCount: 100\n);\n\nvar_dump($chat);", + "matrix->users->retrieveProfile('@alice:example.com');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/v3/profile/$USER_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'create', - endpoint: '/v1/chats', - httpMethod: 'post', - summary: 'Create a chat', - description: 'Create a direct or group chat from participant IDs. Returns the created chat.', - stainlessPath: '(resource) chats > (method) create', - qualified: 'client.chats.create', - params: [ - 'accountID: string;', - 'participantIDs: string[];', - "type: 'single' | 'group';", - 'messageText?: string;', - 'title?: string;', - ], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + name: 'retrieve', + endpoint: '/_matrix/client/v3/user/{userId}/account_data/{type}', + httpMethod: 'get', + summary: 'Get some account data for the user.', + description: + 'Get some account data for the client. This config is only visible to the user\nthat set the account data.', + stainlessPath: '(resource) matrix.users.account_data > (method) retrieve', + qualified: 'client.matrix.users.accountData.retrieve', + params: ['userId: string;', 'type: string;'], + response: 'object', markdown: - "## create\n\n`client.chats.create(accountID: string, participantIDs: string[], type: 'single' | 'group', messageText?: string, title?: string): object`\n\n**post** `/v1/chats`\n\nCreate a direct or group chat from participant IDs. Returns the created chat.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `participantIDs: string[]`\n User IDs to include in the new chat.\n\n- `type: 'single' | 'group'`\n 'single' requires exactly one participantID; 'group' supports multiple participants and optional title.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n- `title?: string`\n Optional title for group chats; ignored for single chats on most networks.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.create({\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n});\n\nconsole.log(chat);\n```", + "## retrieve\n\n`client.matrix.users.accountData.retrieve(userId: string, type: string): object`\n\n**get** `/_matrix/client/v3/user/{userId}/account_data/{type}`\n\nGet some account data for the client. This config is only visible to the user\nthat set the account data.\n\n### Parameters\n\n- `userId: string`\n\n- `type: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.users.accountData.retrieve('org.example.custom.config', { userId: '@alice:example.com' });\n\nconsole.log(accountData);\n```", perLanguage: { typescript: { - method: 'client.chats.create', + method: 'client.matrix.users.accountData.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.create({\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n});\n\nconsole.log(chat);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.users.accountData.retrieve('org.example.custom.config', {\n userId: '@alice:example.com',\n});\n\nconsole.log(accountData);", }, python: { - method: 'chats.create', + method: 'matrix.users.account_data.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.create(\n account_id="accountID",\n participant_ids=["string"],\n type="single",\n)\nprint(chat)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.users.account_data.retrieve(\n type="org.example.custom.config",\n user_id="@alice:example.com",\n)\nprint(account_data)', }, go: { - method: 'client.Chats.New', + method: 'client.Matrix.Users.AccountData.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.New(context.TODO(), beeperdesktopapi.ChatNewParams{\n\t\tAccountID: "accountID",\n\t\tParticipantIDs: []string{"string"},\n\t\tType: beeperdesktopapi.ChatNewParamsTypeSingle,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Users.AccountData.Get(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.config",\n\t\tbeeperdesktopapi.MatrixUserAccountDataGetParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', }, cli: { - method: 'chats create', + method: 'account_data retrieve', example: - "beeper-desktop-cli chats create \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --participant-id string \\\n --type single", + "beeper-desktop-cli matrix:users:account-data retrieve \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --type org.example.custom.config", }, php: { - method: 'chats->create', + method: 'matrix->users->accountData->retrieve', example: - "chats->create(\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n messageText: 'messageText',\n title: 'title',\n);\n\nvar_dump($chat);", + "matrix->users->accountData->retrieve(\n 'org.example.custom.config', userID: '@alice:example.com'\n);\n\nvar_dump($accountData);", }, http: { example: - 'curl http://localhost:23373/v1/chats \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "accountID": "accountID",\n "participantIDs": [\n "string"\n ],\n "type": "single"\n }\'', + 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/account_data/$TYPE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'start', - endpoint: '/v1/chats/start', - httpMethod: 'post', - summary: 'Start a direct chat', + name: 'update', + endpoint: '/_matrix/client/v3/user/{userId}/account_data/{type}', + httpMethod: 'put', + summary: 'Set some account data for the user.', 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+.', - stainlessPath: '(resource) chats > (method) start', - qualified: 'client.chats.start', - params: [ - 'accountID: string;', - 'user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; };', - 'allowInvite?: boolean;', - 'messageText?: string;', - ], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + 'Set some account data for the client. This config is only visible to the user\nthat set the account data. The config will be available to clients through the\ntop-level `account_data` field in the homeserver response to\n[/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).', + stainlessPath: '(resource) matrix.users.account_data > (method) update', + qualified: 'client.matrix.users.accountData.update', + params: ['userId: string;', 'type: string;', 'body: object;'], + response: 'object', markdown: - "## start\n\n`client.chats.start(accountID: string, user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }, allowInvite?: boolean, messageText?: string): object`\n\n**post** `/v1/chats/start`\n\nResolve 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+.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }`\n Merged user-like contact payload used to resolve the best identifier.\n - `id?: string`\n Known user ID when available.\n - `email?: string`\n Email candidate.\n - `fullName?: string`\n Display name hint used for ranking only.\n - `phoneNumber?: string`\n Phone number candidate (E.164 preferred).\n - `username?: string`\n Username/handle candidate.\n\n- `allowInvite?: boolean`\n Whether invite-based DM creation is allowed when required by the platform.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);\n```", + "## update\n\n`client.matrix.users.accountData.update(userId: string, type: string, body: object): object`\n\n**put** `/_matrix/client/v3/user/{userId}/account_data/{type}`\n\nSet some account data for the client. This config is only visible to the user\nthat set the account data. The config will be available to clients through the\ntop-level `account_data` field in the homeserver response to\n[/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).\n\n### Parameters\n\n- `userId: string`\n\n- `type: string`\n\n- `body: object`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.users.accountData.update('org.example.custom.config', {\n userId: '@alice:example.com',\n body: { custom_account_data_key: 'custom_config_value' },\n});\n\nconsole.log(accountData);\n```", perLanguage: { typescript: { - method: 'client.chats.start', + method: 'client.matrix.users.accountData.update', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.users.accountData.update('org.example.custom.config', {\n userId: '@alice:example.com',\n body: { custom_account_data_key: 'custom_config_value' },\n});\n\nconsole.log(accountData);", }, python: { - method: 'chats.start', + method: 'matrix.users.account_data.update', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.chats.start(\n account_id="accountID",\n user={},\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.users.account_data.update(\n type="org.example.custom.config",\n user_id="@alice:example.com",\n body={\n "custom_account_data_key": "custom_config_value"\n },\n)\nprint(account_data)', }, go: { - method: 'client.Chats.Start', + method: 'client.Matrix.Users.AccountData.Update', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Start(context.TODO(), beeperdesktopapi.ChatStartParams{\n\t\tAccountID: "accountID",\n\t\tUser: beeperdesktopapi.ChatStartParamsUser{},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Users.AccountData.Update(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.config",\n\t\tbeeperdesktopapi.MatrixUserAccountDataUpdateParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tBody: map[string]any{\n\t\t\t\t"custom_account_data_key": "custom_config_value",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', }, cli: { - method: 'chats start', + method: 'account_data update', example: - "beeper-desktop-cli chats start \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --user '{}'", + "beeper-desktop-cli matrix:users:account-data update \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --type org.example.custom.config \\\n --body '{custom_account_data_key: custom_config_value}'", }, php: { - method: 'chats->start', + method: 'matrix->users->accountData->update', example: - "chats->start(\n accountID: 'accountID',\n user: [\n 'id' => 'id',\n 'email' => 'email',\n 'fullName' => 'fullName',\n 'phoneNumber' => 'phoneNumber',\n 'username' => 'username',\n ],\n allowInvite: true,\n messageText: 'messageText',\n);\n\nvar_dump($response);", + "matrix->users->accountData->update(\n 'org.example.custom.config',\n userID: '@alice:example.com',\n body: ['custom_account_data_key' => 'custom_config_value'],\n);\n\nvar_dump($accountData);", }, http: { example: - 'curl http://localhost:23373/v1/chats/start \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "accountID": "accountID",\n "user": {}\n }\'', + 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/account_data/$TYPE \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "custom_account_data_key": "custom_config_value"\n }\'', }, }, }, { - name: 'list', - endpoint: '/v1/chats', - httpMethod: 'get', - summary: 'List chats', + name: 'create', + endpoint: '/_matrix/client/v3/createRoom', + httpMethod: 'post', + summary: 'Create a new room', description: - 'List all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.', - stainlessPath: '(resource) chats > (method) list', - qualified: 'client.chats.list', - params: ['accountIDs?: string[];', 'cursor?: string;', "direction?: 'after' | 'before';"], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + "Create a new room with various configuration options.\n\nThe server MUST apply the normal state resolution rules when creating\nthe new room, including checking power levels for each event. It MUST\napply the events implied by the request in the following order:\n\n1. The `m.room.create` event itself. Must be the first event in the\n room.\n\n2. An `m.room.member` event for the creator to join the room. This is\n needed so the remaining events can be sent.\n\n3. A default `m.room.power_levels` event. Overridden by the\n `power_level_content_override` parameter.\n\n In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the room creator (and not\n other members) will be given permission to send state events.\n\n In room versions 12 and later, the room creator is given infinite\n power level and cannot be specified in the `users` field of\n `m.room.power_levels`, so is not listed explicitly.\n\n **Note**: For `trusted_private_chat`, the users specified in the\n `invite` parameter SHOULD also be appended to `additional_creators`\n by the server, per the `creation_content` parameter.\n\n If the room's version is 12 or higher, the power level for sending\n `m.room.tombstone` events MUST explicitly be higher than `state_default`.\n For example, set to 150 instead of 100.\n\n4. An `m.room.canonical_alias` event if `room_alias_name` is given.\n\n5. Events set by the `preset`. Currently these are the `m.room.join_rules`,\n `m.room.history_visibility`, and `m.room.guest_access` state events.\n\n6. Events listed in `initial_state`, in the order that they are\n listed.\n\n7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`\n state events).\n\n8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with\n `membership: invite` and `m.room.third_party_invite`).\n\nThe available presets do the following with respect to room state:\n\n| Preset | `join_rules` | `history_visibility` | `guest_access` | Other |\n|------------------------|--------------|----------------------|----------------|-------|\n| `private_chat` | `invite` | `shared` | `can_join` | |\n| `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. |\n| `public_chat` | `public` | `shared` | `forbidden` | |\n\nThe server will create a `m.room.create` event in the room with the\nrequesting user as the creator, alongside other keys provided in the\n`creation_content` or implied by behaviour of `creation_content`.", + stainlessPath: '(resource) matrix.rooms > (method) create', + qualified: 'client.matrix.rooms.create', + params: [ + 'creation_content?: object;', + 'initial_state?: { content: object; type: string; state_key?: string; }[];', + 'invite?: string[];', + 'invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[];', + 'is_direct?: boolean;', + 'name?: string;', + 'power_level_content_override?: object;', + "preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat';", + 'room_alias_name?: string;', + 'room_version?: string;', + 'topic?: string;', + "visibility?: 'public' | 'private';", + ], + response: '{ room_id: string; }', markdown: - "## list\n\n`client.chats.list(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before'): object`\n\n**get** `/v1/chats`\n\nList all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit to specific account IDs. If omitted, fetches from all accounts.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n Chat with optional last message preview.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chatListResponse of client.chats.list()) {\n console.log(chatListResponse);\n}\n```", + "## create\n\n`client.matrix.rooms.create(creation_content?: object, initial_state?: { content: object; type: string; state_key?: string; }[], invite?: string[], invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[], is_direct?: boolean, name?: string, power_level_content_override?: object, preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat', room_alias_name?: string, room_version?: string, topic?: string, visibility?: 'public' | 'private'): { room_id: string; }`\n\n**post** `/_matrix/client/v3/createRoom`\n\nCreate a new room with various configuration options.\n\nThe server MUST apply the normal state resolution rules when creating\nthe new room, including checking power levels for each event. It MUST\napply the events implied by the request in the following order:\n\n1. The `m.room.create` event itself. Must be the first event in the\n room.\n\n2. An `m.room.member` event for the creator to join the room. This is\n needed so the remaining events can be sent.\n\n3. A default `m.room.power_levels` event. Overridden by the\n `power_level_content_override` parameter.\n\n In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the room creator (and not\n other members) will be given permission to send state events.\n\n In room versions 12 and later, the room creator is given infinite\n power level and cannot be specified in the `users` field of\n `m.room.power_levels`, so is not listed explicitly.\n\n **Note**: For `trusted_private_chat`, the users specified in the\n `invite` parameter SHOULD also be appended to `additional_creators`\n by the server, per the `creation_content` parameter.\n\n If the room's version is 12 or higher, the power level for sending\n `m.room.tombstone` events MUST explicitly be higher than `state_default`.\n For example, set to 150 instead of 100.\n\n4. An `m.room.canonical_alias` event if `room_alias_name` is given.\n\n5. Events set by the `preset`. Currently these are the `m.room.join_rules`,\n `m.room.history_visibility`, and `m.room.guest_access` state events.\n\n6. Events listed in `initial_state`, in the order that they are\n listed.\n\n7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`\n state events).\n\n8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with\n `membership: invite` and `m.room.third_party_invite`).\n\nThe available presets do the following with respect to room state:\n\n| Preset | `join_rules` | `history_visibility` | `guest_access` | Other |\n|------------------------|--------------|----------------------|----------------|-------|\n| `private_chat` | `invite` | `shared` | `can_join` | |\n| `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. |\n| `public_chat` | `public` | `shared` | `forbidden` | |\n\nThe server will create a `m.room.create` event in the room with the\nrequesting user as the creator, alongside other keys provided in the\n`creation_content` or implied by behaviour of `creation_content`.\n\n### Parameters\n\n- `creation_content?: object`\n Extra keys, such as `m.federate`, to be added to the content\nof the [`m.room.create`](https://spec.matrix.org/v1.18/client-server-api/#mroomcreate) event.\n\nThe server will overwrite the following\nkeys: `creator`, `room_version`. Future versions of the specification\nmay allow the server to overwrite other keys.\n\nWhen using the `trusted_private_chat` preset, the server SHOULD combine\n`additional_creators` specified here and the `invite` array into the\neventual `m.room.create` event's `additional_creators`, deduplicating\nbetween the two parameters.\n\n- `initial_state?: { content: object; type: string; state_key?: string; }[]`\n A list of state events to set in the new room. This allows\nthe user to override the default state events set in the new\nroom. The expected format of the state events are an object\nwith type, state_key and content keys set.\n\nTakes precedence over events set by `preset`, but gets\noverridden by `name` and `topic` keys.\n\n- `invite?: string[]`\n A list of user IDs to invite to the room. This will tell the\nserver to invite everyone in the list to the newly created room.\n\n- `invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[]`\n A list of objects representing third-party IDs to invite into\nthe room.\n\n- `is_direct?: boolean`\n This flag makes the server set the `is_direct` flag on the\n`m.room.member` events sent to the users in `invite` and\n`invite_3pid`. See [Direct Messaging](https://spec.matrix.org/v1.18/client-server-api/#direct-messaging) for more information.\n\n- `name?: string`\n If this is included, an [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname) event\nwill be sent into the room to indicate the name for the room.\nThis overwrites any [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname)\nevent in `initial_state`.\n\n- `power_level_content_override?: object`\n The power level content to override in the default power level\nevent. This object is applied on top of the generated\n[`m.room.power_levels`](https://spec.matrix.org/v1.18/client-server-api/#mroompower_levels)\nevent content prior to it being sent to the room. Defaults to\noverriding nothing.\n\n- `preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat'`\n Convenience parameter for setting various default state events\nbased on a preset.\n\nIf unspecified, the server should use the `visibility` to determine\nwhich preset to use. A visibility of `public` equates to a preset of\n`public_chat` and `private` visibility equates to a preset of\n`private_chat`.\n\n- `room_alias_name?: string`\n The desired room alias **local part**. If this is included, a\nroom alias will be created and mapped to the newly created\nroom. The alias will belong on the *same* homeserver which\ncreated the room. For example, if this was set to \"foo\" and\nsent to the homeserver \"example.com\" the complete room alias\nwould be `#foo:example.com`.\n\nThe complete room alias will become the canonical alias for\nthe room and an `m.room.canonical_alias` event will be sent\ninto the room.\n\n- `room_version?: string`\n The room version to set for the room. If not provided, the homeserver is\nto use its configured default. If provided, the homeserver will return a\n400 error with the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not\nsupport the room version.\n\n- `topic?: string`\n If this is included, an [`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic)\nevent with a `text/plain` mimetype will be sent into the room\nto indicate the topic for the room. This overwrites any\n[`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic) event in `initial_state`.\n\n- `visibility?: 'public' | 'private'`\n The room's visibility in the server's\n[published room directory](https://spec.matrix.org/v1.18/client-server-api#published-room-directory).\nDefaults to `private`.\n\n### Returns\n\n- `{ room_id: string; }`\n Information about the newly created room.\n\n - `room_id: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst room = await client.matrix.rooms.create();\n\nconsole.log(room);\n```", perLanguage: { typescript: { - method: 'client.chats.list', + method: 'client.matrix.rooms.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const chatListResponse of client.chats.list()) {\n console.log(chatListResponse);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst room = await client.matrix.rooms.create();\n\nconsole.log(room.room_id);", }, python: { - method: 'chats.list', + method: 'matrix.rooms.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.chats.list()\npage = page.items[0]\nprint(page)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nroom = client.matrix.rooms.create()\nprint(room.room_id)', }, go: { - method: 'client.Chats.List', + method: 'client.Matrix.Rooms.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.List(context.TODO(), beeperdesktopapi.ChatListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\troom, err := client.Matrix.Rooms.New(context.TODO(), beeperdesktopapi.MatrixRoomNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", room.RoomID)\n}\n', }, cli: { - method: 'chats list', - example: "beeper-desktop-cli chats list \\\n --access-token 'My Access Token'", + method: 'rooms create', + example: "beeper-desktop-cli matrix:rooms create \\\n --access-token 'My Access Token'", }, php: { - method: 'chats->list', + method: 'matrix->rooms->create', example: - "chats->list(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n);\n\nvar_dump($page);", + "matrix->rooms->create(\n creationContent: ['m.federate' => false],\n initialState: [\n ['content' => (object) [], 'type' => 'type', 'stateKey' => 'state_key']\n ],\n invite: ['string'],\n invite3pid: [\n [\n 'address' => 'cheeky@monkey.com',\n 'idAccessToken' => 'abc123_OpaqueString',\n 'idServer' => 'matrix.org',\n 'medium' => 'email',\n ],\n ],\n isDirect: true,\n name: 'The Grand Duke Pub',\n powerLevelContentOverride: (object) [],\n preset: 'public_chat',\n roomAliasName: 'thepub',\n roomVersion: '1',\n topic: 'All about happy hour',\n visibility: 'public',\n);\n\nvar_dump($room);", }, http: { example: - 'curl http://localhost:23373/v1/chats \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/v3/createRoom \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "creation_content": {\n "m.federate": false\n },\n "name": "The Grand Duke Pub",\n "preset": "public_chat",\n "room_alias_name": "thepub",\n "room_version": "1",\n "topic": "All about happy hour"\n }\'', }, }, }, { - name: 'search', - endpoint: '/v1/chats/search', - httpMethod: 'get', - summary: 'Search chats', - description: 'Search chats by title, network, or participant names.', - stainlessPath: '(resource) chats > (method) search', - qualified: 'client.chats.search', + name: 'join', + endpoint: '/_matrix/client/v3/join/{roomIdOrAlias}', + httpMethod: 'post', + summary: 'Join the requesting user to a particular room.', + description: + "*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.\n\nThis API starts a user's participation in a particular room, if that user\nis allowed to participate in that room. After this call, the client is\nallowed to see all current state events in the room, and all subsequent\nevents associated with the room until the user leaves the room.\n\nAfter a user has joined a room, the room will appear as an entry in the\nresponse of the [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync)\nand [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) APIs.", + stainlessPath: '(resource) matrix.rooms > (method) join', + qualified: 'client.matrix.rooms.join', params: [ - 'accountIDs?: string[];', - 'cursor?: string;', - "direction?: 'after' | 'before';", - "inbox?: 'primary' | 'low-priority' | 'archive';", - 'includeMuted?: boolean;', - 'lastActivityAfter?: string;', - 'lastActivityBefore?: string;', - 'limit?: number;', - 'query?: string;', - "scope?: 'titles' | 'participants';", - "type?: 'single' | 'group' | 'any';", - 'unreadOnly?: boolean;', + 'roomIdOrAlias: string;', + 'via?: string[];', + 'reason?: string;', + 'third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; };', ], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + response: '{ room_id: string; }', markdown: - "## search\n\n`client.chats.search(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before', inbox?: 'primary' | 'low-priority' | 'archive', includeMuted?: boolean, lastActivityAfter?: string, lastActivityBefore?: string, limit?: number, query?: string, scope?: 'titles' | 'participants', type?: 'single' | 'group' | 'any', unreadOnly?: boolean): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/search`\n\nSearch chats by title, network, or participant names.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Provide an array of account IDs to filter chats from specific messaging accounts only\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `inbox?: 'primary' | 'low-priority' | 'archive'`\n Filter by inbox type: \"primary\" (non-archived, non-low-priority), \"low-priority\", or \"archive\". If not specified, shows all chats.\n\n- `includeMuted?: boolean`\n 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.\n\n- `lastActivityAfter?: string`\n Provide an ISO datetime string to only retrieve chats with last activity after this time\n\n- `lastActivityBefore?: string`\n Provide an ISO datetime string to only retrieve chats with last activity before this time\n\n- `limit?: number`\n Set the maximum number of chats to retrieve. Valid range: 1-200, default is 50\n\n- `query?: string`\n Literal token search (non-semantic). Use single words users type (e.g., \"dinner\"). When multiple words provided, ALL must match. Case-insensitive.\n\n- `scope?: 'titles' | 'participants'`\n Search scope: 'titles' matches title + network; 'participants' matches participant names.\n\n- `type?: 'single' | 'group' | 'any'`\n Specify the type of chats to retrieve: use \"single\" for direct messages, \"group\" for group chats, or \"any\" to get all types\n\n- `unreadOnly?: boolean`\n Set to true to only retrieve chats that have unread messages\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat);\n}\n```", + "## join\n\n`client.matrix.rooms.join(roomIdOrAlias: string, via?: string[], reason?: string, third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; }): { room_id: string; }`\n\n**post** `/_matrix/client/v3/join/{roomIdOrAlias}`\n\n*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.\n\nThis API starts a user's participation in a particular room, if that user\nis allowed to participate in that room. After this call, the client is\nallowed to see all current state events in the room, and all subsequent\nevents associated with the room until the user leaves the room.\n\nAfter a user has joined a room, the room will appear as an entry in the\nresponse of the [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync)\nand [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) APIs.\n\n### Parameters\n\n- `roomIdOrAlias: string`\n\n- `via?: string[]`\n The servers to attempt to join the room through. One of the servers\nmust be participating in the room.\n\n- `reason?: string`\n Optional reason to be included as the `reason` on the subsequent\nmembership event.\n\n- `third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; }`\n A signature of an `m.third_party_invite` token to prove that this user\nowns a third-party identity which has been invited to the room.\n - `token: string`\n The state key of the m.third_party_invite event.\n - `mxid: string`\n The Matrix ID of the invitee.\n - `sender: string`\n The Matrix ID of the user who issued the invite.\n - `signatures: object`\n A signatures object containing a signature of the entire signed object.\n\n### Returns\n\n- `{ room_id: string; }`\n\n - `room_id: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.rooms.join('!monkeys:matrix.org');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.chats.search', + method: 'client.matrix.rooms.join', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat.id);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.rooms.join('!monkeys:matrix.org');\n\nconsole.log(response.room_id);", }, python: { - method: 'chats.search', + method: 'matrix.rooms.join', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.chats.search()\npage = page.items[0]\nprint(page.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.rooms.join(\n room_id_or_alias="!monkeys:matrix.org",\n)\nprint(response.room_id)', }, go: { - method: 'client.Chats.Search', + method: 'client.Matrix.Rooms.Join', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.Search(context.TODO(), beeperdesktopapi.ChatSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Rooms.Join(\n\t\tcontext.TODO(),\n\t\t"!monkeys:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomJoinParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.RoomID)\n}\n', }, cli: { - method: 'chats search', - example: "beeper-desktop-cli chats search \\\n --access-token 'My Access Token'", + method: 'rooms join', + example: + "beeper-desktop-cli matrix:rooms join \\\n --access-token 'My Access Token' \\\n --room-id-or-alias '!monkeys:matrix.org'", }, php: { - method: 'chats->search', + method: 'matrix->rooms->join', example: - "chats->search(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n inbox: 'primary',\n includeMuted: true,\n lastActivityAfter: new \\DateTimeImmutable('2019-12-27T18:11:19.117Z'),\n lastActivityBefore: new \\DateTimeImmutable('2019-12-27T18:11:19.117Z'),\n limit: 1,\n query: 'x',\n scope: 'titles',\n type: 'single',\n unreadOnly: true,\n);\n\nvar_dump($page);", + "matrix->rooms->join(\n '!monkeys:matrix.org',\n via: ['string'],\n reason: 'Looking for support',\n thirdPartySigned: [\n 'token' => 'random8nonce',\n 'mxid' => 'bob',\n 'sender' => 'alice',\n 'signatures' => ['example.org' => ['ed25519:0' => 'some9signature']],\n ],\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/v3/join/$ROOM_ID_OR_ALIAS \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reason": "Looking for support"\n }\'', }, }, }, { - name: 'archive', - endpoint: '/v1/chats/{chatID}/archive', + name: 'leave', + endpoint: '/_matrix/client/v3/rooms/{roomId}/leave', httpMethod: 'post', - summary: 'Archive or unarchive a chat', + summary: 'Stop the requesting user participating in a particular room.', description: - 'Archive or unarchive a chat. Set archived=true to move to archive, archived=false to move back to inbox', - stainlessPath: '(resource) chats > (method) archive', - qualified: 'client.chats.archive', - params: ['chatID: string;', 'archived?: boolean;'], + "This API stops a user participating in a particular room.\n\nIf the user was already in the room, they will no longer be able to see\nnew events in the room. If the room requires an invite to join, they\nwill need to be re-invited before they can re-join.\n\nIf the user was invited to the room, but had not joined, this call\nserves to reject the invite.\n\nServers MAY additionally forget the room when this endpoint is called –\njust as if the user had also invoked [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget).\nServers that do this, MUST inform clients about this behavior using the\n[`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability)\ncapability.\n\nIf the server doesn't automatically forget the room, the user will still be\nallowed to retrieve history from the room which they were previously allowed\nto see.", + stainlessPath: '(resource) matrix.rooms > (method) leave', + qualified: 'client.matrix.rooms.leave', + params: ['roomId: string;', 'reason?: string;'], + response: 'object', markdown: - "## archive\n\n`client.chats.archive(chatID: string, archived?: boolean): void`\n\n**post** `/v1/chats/{chatID}/archive`\n\nArchive or unarchive a chat. Set archived=true to move to archive, archived=false to move back to inbox\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `archived?: boolean`\n True to archive, false to unarchive\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", + "## leave\n\n`client.matrix.rooms.leave(roomId: string, reason?: string): object`\n\n**post** `/_matrix/client/v3/rooms/{roomId}/leave`\n\nThis API stops a user participating in a particular room.\n\nIf the user was already in the room, they will no longer be able to see\nnew events in the room. If the room requires an invite to join, they\nwill need to be re-invited before they can re-join.\n\nIf the user was invited to the room, but had not joined, this call\nserves to reject the invite.\n\nServers MAY additionally forget the room when this endpoint is called –\njust as if the user had also invoked [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget).\nServers that do this, MUST inform clients about this behavior using the\n[`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability)\ncapability.\n\nIf the server doesn't automatically forget the room, the user will still be\nallowed to retrieve history from the room which they were previously allowed\nto see.\n\n### Parameters\n\n- `roomId: string`\n\n- `reason?: string`\n Optional reason to be included as the `reason` on the subsequent\nmembership event.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.rooms.leave('!nkl290a:matrix.org');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.chats.archive', + method: 'client.matrix.rooms.leave', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com');", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.rooms.leave('!nkl290a:matrix.org');\n\nconsole.log(response);", }, python: { - method: 'chats.archive', + method: 'matrix.rooms.leave', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.archive(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.rooms.leave(\n room_id="!nkl290a:matrix.org",\n)\nprint(response)', }, go: { - method: 'client.Chats.Archive', + method: 'client.Matrix.Rooms.Leave', example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Archive(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatArchiveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Rooms.Leave(\n\t\tcontext.TODO(),\n\t\t"!nkl290a:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomLeaveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'chats archive', + method: 'rooms leave', example: - "beeper-desktop-cli chats archive \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:rooms leave \\\n --access-token 'My Access Token' \\\n --room-id '!nkl290a:matrix.org'", }, php: { - method: 'chats->archive', + method: 'matrix->rooms->leave', example: - "chats->archive(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', archived: true\n);\n\nvar_dump($result);", + "matrix->rooms->leave(\n '!nkl290a:matrix.org', reason: 'Saying farewell - thanks for the support!'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/archive \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/leave \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reason": "Saying farewell - thanks for the support!"\n }\'', }, }, }, { - name: 'update', - endpoint: '/v1/chats/{chatID}', - httpMethod: 'patch', - summary: 'Update chat', + name: 'retrieve', + endpoint: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', + httpMethod: 'get', + summary: 'Get some account data for the user that is specific to a room.', 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.', - stainlessPath: '(resource) chats > (method) update', - qualified: 'client.chats.update', - params: [ - 'chatID: string;', - 'description?: string;', - 'draft?: { text: string; attachments?: object; };', - 'imgURL?: string;', - 'isArchived?: boolean;', - 'isLowPriority?: boolean;', - 'isMuted?: boolean;', - 'isPinned?: boolean;', - 'messageExpirySeconds?: number;', - 'title?: string;', - ], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + 'Get some account data for the client on a given room. This config is only\nvisible to the user that set the account data.', + stainlessPath: '(resource) matrix.rooms.account_data > (method) retrieve', + qualified: 'client.matrix.rooms.accountData.retrieve', + params: ['userId: string;', 'roomId: string;', 'type: string;'], + response: 'object', markdown: - "## update\n\n`client.chats.update(chatID: string, description?: string, draft?: { text: string; attachments?: object; }, imgURL?: string, isArchived?: boolean, isLowPriority?: boolean, isMuted?: boolean, isPinned?: boolean, messageExpirySeconds?: number, title?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**patch** `/v1/chats/{chatID}`\n\nUpdate 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.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `description?: string`\n Group chat description/topic. Support depends on the chat account and chat permissions.\n\n- `draft?: { text: string; attachments?: object; }`\n Draft object to set or clear. Non-empty drafts are only accepted when the current draft is empty. Send draft=null to clear text and attachments together before setting a new draft.\n - `text: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n - `attachments?: object`\n Draft attachments keyed by attachment ID. Each attachment must reference an uploadID returned by the upload file endpoint.\n\n- `imgURL?: string`\n Local filesystem path to a group chat avatar image. Support depends on the chat account and chat permissions.\n\n- `isArchived?: boolean`\n Archive or unarchive the chat.\n\n- `isLowPriority?: boolean`\n Mark or unmark the chat as low priority when supported by the account.\n\n- `isMuted?: boolean`\n Mute or unmute the chat.\n\n- `isPinned?: boolean`\n Pin or unpin the chat when supported by the account.\n\n- `messageExpirySeconds?: number`\n Disappearing-message timer in seconds, or null to clear when supported.\n\n- `title?: string`\n Custom chat title. Support depends on the chat account and chat permissions.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## retrieve\n\n`client.matrix.rooms.accountData.retrieve(userId: string, roomId: string, type: string): object`\n\n**get** `/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}`\n\nGet some account data for the client on a given room. This config is only\nvisible to the user that set the account data.\n\n### Parameters\n\n- `userId: string`\n\n- `roomId: string`\n\n- `type: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.rooms.accountData.retrieve('org.example.custom.room.config', { userId: '@alice:example.com', roomId: '!726s6s6q:example.com' });\n\nconsole.log(accountData);\n```", perLanguage: { typescript: { - method: 'client.chats.update', + method: 'client.matrix.rooms.accountData.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.rooms.accountData.retrieve(\n 'org.example.custom.room.config',\n { userId: '@alice:example.com', roomId: '!726s6s6q:example.com' },\n);\n\nconsole.log(accountData);", }, python: { - method: 'chats.update', + method: 'matrix.rooms.account_data.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.update(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.rooms.account_data.retrieve(\n type="org.example.custom.room.config",\n user_id="@alice:example.com",\n room_id="!726s6s6q:example.com",\n)\nprint(account_data)', }, go: { - method: 'client.Chats.Update', + method: 'client.Matrix.Rooms.AccountData.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Update(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Rooms.AccountData.Get(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.room.config",\n\t\tbeeperdesktopapi.MatrixRoomAccountDataGetParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tRoomID: "!726s6s6q:example.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', }, cli: { - method: 'chats update', + method: 'account_data retrieve', example: - "beeper-desktop-cli chats update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:rooms:account-data retrieve \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --room-id '!726s6s6q:example.com' \\\n --type org.example.custom.room.config", }, php: { - method: 'chats->update', + method: 'matrix->rooms->accountData->retrieve', example: - "chats->update(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n description: 'description',\n draft: [\n 'text' => 'text',\n 'attachments' => [\n 'foo' => [\n 'uploadID' => 'uploadID',\n 'id' => 'id',\n 'duration' => 0,\n 'fileName' => 'fileName',\n 'mimeType' => 'mimeType',\n 'size' => ['height' => 0, 'width' => 0],\n 'type' => 'image',\n ],\n ],\n ],\n imgURL: 'imgURL',\n isArchived: true,\n isLowPriority: true,\n isMuted: true,\n isPinned: true,\n messageExpirySeconds: 0,\n title: 'title',\n);\n\nvar_dump($chat);", + "matrix->rooms->accountData->retrieve(\n 'org.example.custom.room.config',\n userID: '@alice:example.com',\n roomID: '!726s6s6q:example.com',\n);\n\nvar_dump($accountData);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID \\\n -X PATCH \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/rooms/$ROOM_ID/account_data/$TYPE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'mark_read', - endpoint: '/v1/chats/{chatID}/read', - httpMethod: 'post', - summary: 'Mark a chat as read', - description: 'Mark a chat as read, optionally through a specific message ID.', - stainlessPath: '(resource) chats > (method) mark_read', - qualified: 'client.chats.markRead', - params: ['chatID: string;', 'messageID?: string;'], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + name: 'update', + endpoint: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', + httpMethod: 'put', + summary: 'Set some account data for the user that is specific to a room.', + description: + 'Set some account data for the client on a given room. This config is only\nvisible to the user that set the account data. The config will be delivered to\nclients in the per-room entries via [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).', + stainlessPath: '(resource) matrix.rooms.account_data > (method) update', + qualified: 'client.matrix.rooms.accountData.update', + params: ['userId: string;', 'roomId: string;', 'type: string;', 'body: object;'], + response: 'object', markdown: - "## mark_read\n\n`client.chats.markRead(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/read`\n\nMark a chat as read, optionally through a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark read through.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## update\n\n`client.matrix.rooms.accountData.update(userId: string, roomId: string, type: string, body: object): object`\n\n**put** `/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}`\n\nSet some account data for the client on a given room. This config is only\nvisible to the user that set the account data. The config will be delivered to\nclients in the per-room entries via [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).\n\n### Parameters\n\n- `userId: string`\n\n- `roomId: string`\n\n- `type: string`\n\n- `body: object`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.rooms.accountData.update('org.example.custom.room.config', {\n userId: '@alice:example.com',\n roomId: '!726s6s6q:example.com',\n body: { custom_account_data_key: 'custom_account_data_value' },\n});\n\nconsole.log(accountData);\n```", perLanguage: { typescript: { - method: 'client.chats.markRead', + method: 'client.matrix.rooms.accountData.update', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.rooms.accountData.update('org.example.custom.room.config', {\n userId: '@alice:example.com',\n roomId: '!726s6s6q:example.com',\n body: { custom_account_data_key: 'custom_account_data_value' },\n});\n\nconsole.log(accountData);", }, python: { - method: 'chats.mark_read', + method: 'matrix.rooms.account_data.update', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.mark_read(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.rooms.account_data.update(\n type="org.example.custom.room.config",\n user_id="@alice:example.com",\n room_id="!726s6s6q:example.com",\n body={\n "custom_account_data_key": "custom_account_data_value"\n },\n)\nprint(account_data)', }, go: { - method: 'client.Chats.MarkRead', + method: 'client.Matrix.Rooms.AccountData.Update', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkRead(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkReadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Rooms.AccountData.Update(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.room.config",\n\t\tbeeperdesktopapi.MatrixRoomAccountDataUpdateParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tRoomID: "!726s6s6q:example.com",\n\t\t\tBody: map[string]any{\n\t\t\t\t"custom_account_data_key": "custom_account_data_value",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', }, cli: { - method: 'chats mark_read', + method: 'account_data update', example: - "beeper-desktop-cli chats mark-read \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:rooms:account-data update \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --room-id '!726s6s6q:example.com' \\\n --type org.example.custom.room.config \\\n --body '{custom_account_data_key: custom_account_data_value}'", }, php: { - method: 'chats->markRead', + method: 'matrix->rooms->accountData->update', example: - "chats->markRead(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($chat);", + "matrix->rooms->accountData->update(\n 'org.example.custom.room.config',\n userID: '@alice:example.com',\n roomID: '!726s6s6q:example.com',\n body: ['custom_account_data_key' => 'custom_account_data_value'],\n);\n\nvar_dump($accountData);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/read \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/rooms/$ROOM_ID/account_data/$TYPE \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "custom_account_data_key": "custom_account_data_value"\n }\'', }, }, }, { - name: 'mark_unread', - endpoint: '/v1/chats/{chatID}/unread', - httpMethod: 'post', - summary: 'Mark a chat as unread', - description: 'Mark a chat as unread, optionally from a specific message ID.', - stainlessPath: '(resource) chats > (method) mark_unread', - qualified: 'client.chats.markUnread', - params: ['chatID: string;', 'messageID?: string;'], + name: 'list', + endpoint: '/_matrix/client/v3/rooms/{roomId}/state', + httpMethod: 'get', + summary: 'Get all state events in the current state of a room.', + description: 'Get the state events for the current state of a room.', + stainlessPath: '(resource) matrix.rooms.state > (method) list', + qualified: 'client.matrix.rooms.state.list', + params: ['roomId: string;'], response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + '{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }[]', markdown: - "## mark_unread\n\n`client.chats.markUnread(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/unread`\n\nMark a chat as unread, optionally from a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark unread from.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## list\n\n`client.matrix.rooms.state.list(roomId: string): { content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: object; }[]`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/state`\n\nGet the state events for the current state of a room.\n\n### Parameters\n\n- `roomId: string`\n\n### Returns\n\n- `{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }[]`\n If the user is a member of the room this will be the\ncurrent state of the room as a list of events. If the user\nhas left the room then this will be the state of the room\nwhen they left as a list of events.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst states = await client.matrix.rooms.state.list('!636q39766251:example.com');\n\nconsole.log(states);\n```", perLanguage: { typescript: { - method: 'client.chats.markUnread', + method: 'client.matrix.rooms.state.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst states = await client.matrix.rooms.state.list('!636q39766251:example.com');\n\nconsole.log(states);", }, python: { - method: 'chats.mark_unread', + method: 'matrix.rooms.state.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.mark_unread(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nstates = client.matrix.rooms.state.list(\n "!636q39766251:example.com",\n)\nprint(states)', }, go: { - method: 'client.Chats.MarkUnread', + method: 'client.Matrix.Rooms.State.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkUnread(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkUnreadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tstates, err := client.Matrix.Rooms.State.List(context.TODO(), "!636q39766251:example.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", states)\n}\n', }, cli: { - method: 'chats mark_unread', + method: 'state list', example: - "beeper-desktop-cli chats mark-unread \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:rooms:state list \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:example.com'", }, php: { - method: 'chats->markUnread', + method: 'matrix->rooms->state->list', example: - "chats->markUnread(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($chat);", + "matrix->rooms->state->list('!636q39766251:example.com');\n\nvar_dump($states);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/unread \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/state \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'notify_anyway', - endpoint: '/v1/chats/{chatID}/notify-anyway', - httpMethod: 'post', - summary: 'Notify anyway', + name: 'retrieve', + endpoint: '/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}', + httpMethod: 'get', + summary: 'Get the state identified by the type and key.', description: - 'Force a delivery notification when supported by the underlying network. Currently intended for iMessage on macOS; unsupported networks return an error.', - stainlessPath: '(resource) chats > (method) notify_anyway', - qualified: 'client.chats.notifyAnyway', - params: ['chatID: string;'], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + 'Looks up the contents of a state event in a room. If the user is\njoined to the room then the state is taken from the current\nstate of the room. If the user has left the room then the state is\ntaken from the state of the room when they left.', + stainlessPath: '(resource) matrix.rooms.state > (method) retrieve', + qualified: 'client.matrix.rooms.state.retrieve', + params: ['roomId: string;', 'eventType: string;', 'stateKey: string;', "format?: 'content' | 'event';"], + response: 'object', markdown: - "## notify_anyway\n\n`client.chats.notifyAnyway(chatID: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/notify-anyway`\n\nForce a delivery notification when supported by the underlying network. Currently intended for iMessage on macOS; unsupported networks return an error.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## retrieve\n\n`client.matrix.rooms.state.retrieve(roomId: string, eventType: string, stateKey: string, format?: 'content' | 'event'): object`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}`\n\nLooks up the contents of a state event in a room. If the user is\njoined to the room then the state is taken from the current\nstate of the room. If the user has left the room then the state is\ntaken from the state of the room when they left.\n\n### Parameters\n\n- `roomId: string`\n\n- `eventType: string`\n\n- `stateKey: string`\n\n- `format?: 'content' | 'event'`\n The format to use for the returned data. `content` (the default) will\nreturn only the content of the state event. `event` will return the entire\nevent in the usual format suitable for clients, including fields like event\nID, sender and timestamp.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst state = await client.matrix.rooms.state.retrieve('state_key', { roomId: '!636q39766251:example.com', eventType: 'm.room.name' });\n\nconsole.log(state);\n```", perLanguage: { typescript: { - method: 'client.chats.notifyAnyway', + method: 'client.matrix.rooms.state.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst state = await client.matrix.rooms.state.retrieve('state_key', {\n roomId: '!636q39766251:example.com',\n eventType: 'm.room.name',\n});\n\nconsole.log(state);", }, python: { - method: 'chats.notify_anyway', + method: 'matrix.rooms.state.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.notify_anyway(\n "!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nstate = client.matrix.rooms.state.retrieve(\n state_key="state_key",\n room_id="!636q39766251:example.com",\n event_type="m.room.name",\n)\nprint(state)', }, go: { - method: 'client.Chats.NotifyAnyway', + method: 'client.Matrix.Rooms.State.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.NotifyAnyway(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatNotifyAnywayParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tstate, err := client.Matrix.Rooms.State.Get(\n\t\tcontext.TODO(),\n\t\t"state_key",\n\t\tbeeperdesktopapi.MatrixRoomStateGetParams{\n\t\t\tRoomID: "!636q39766251:example.com",\n\t\t\tEventType: "m.room.name",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", state)\n}\n', }, cli: { - method: 'chats notify_anyway', + method: 'state retrieve', example: - "beeper-desktop-cli chats notify-anyway \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:rooms:state retrieve \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:example.com' \\\n --event-type m.room.name \\\n --state-key state_key", }, php: { - method: 'chats->notifyAnyway', + method: 'matrix->rooms->state->retrieve', example: - "chats->notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nvar_dump($chat);", + "matrix->rooms->state->retrieve(\n 'state_key',\n roomID: '!636q39766251:example.com',\n eventType: 'm.room.name',\n format: 'content',\n);\n\nvar_dump($state);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/notify-anyway \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/state/$EVENT_TYPE/$STATE_KEY \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'create', - endpoint: '/v1/chats/{chatID}/reminders', - httpMethod: 'post', - summary: 'Create a chat reminder', - description: 'Set a reminder for a chat at a specific time', - stainlessPath: '(resource) chats.reminders > (method) create', - qualified: 'client.chats.reminders.create', - params: ['chatID: string;', 'reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; };'], + name: 'retrieve', + endpoint: '/_matrix/client/v3/rooms/{roomId}/event/{eventId}', + httpMethod: 'get', + summary: 'Get a single event by event ID.', + description: + 'Get a single event based on `roomId/eventId`. You must have permission to\nretrieve this event e.g. by being a member in the room for this event.', + stainlessPath: '(resource) matrix.rooms.events > (method) retrieve', + qualified: 'client.matrix.rooms.events.retrieve', + params: ['roomId: string;', 'eventId: string;'], + response: + '{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }', markdown: - "## create\n\n`client.chats.reminders.create(chatID: string, reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }): void`\n\n**post** `/v1/chats/{chatID}/reminders`\n\nSet a reminder for a chat at a specific time\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }`\n Reminder configuration\n - `remindAt: string`\n Timestamp when the reminder should trigger.\n - `dismissOnIncomingMessage?: boolean`\n Cancel reminder if someone messages in the chat\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', { reminder: { remindAt: '2025-08-31T23:30:12.520Z' } })\n```", + "## retrieve\n\n`client.matrix.rooms.events.retrieve(roomId: string, eventId: string): { content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: object; }`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/event/{eventId}`\n\nGet a single event based on `roomId/eventId`. You must have permission to\nretrieve this event e.g. by being a member in the room for this event.\n\n### Parameters\n\n- `roomId: string`\n\n- `eventId: string`\n\n### Returns\n\n- `{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }`\n The format used for events when they are returned from a homeserver to a client\nvia the Client-Server API, or sent to an Application Service via the Application Services API.\n\n - `content: object`\n - `event_id: string`\n - `origin_server_ts: number`\n - `room_id: string`\n - `sender: string`\n - `type: string`\n - `state_key?: string`\n - `unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst event = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', { roomId: '!636q39766251:matrix.org' });\n\nconsole.log(event);\n```", perLanguage: { typescript: { - method: 'client.chats.reminders.create', + method: 'client.matrix.rooms.events.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', {\n reminder: { remindAt: '2025-08-31T23:30:12.520Z' },\n});", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst event = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', {\n roomId: '!636q39766251:matrix.org',\n});\n\nconsole.log(event.event_id);", }, python: { - method: 'chats.reminders.create', + method: 'matrix.rooms.events.retrieve', example: - 'import os\nfrom datetime import datetime\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.reminders.create(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n reminder={\n "remind_at": datetime.fromisoformat("2025-08-31T23:30:12.520")\n },\n)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nevent = client.matrix.rooms.events.retrieve(\n event_id="$asfDuShaf7Gafaw:matrix.org",\n room_id="!636q39766251:matrix.org",\n)\nprint(event.event_id)', }, go: { - method: 'client.Chats.Reminders.New', + method: 'client.Matrix.Rooms.Events.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"time"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.New(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatReminderNewParams{\n\t\t\tReminder: beeperdesktopapi.ChatReminderNewParamsReminder{\n\t\t\t\tRemindAt: time.Now(),\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tevent, err := client.Matrix.Rooms.Events.Get(\n\t\tcontext.TODO(),\n\t\t"$asfDuShaf7Gafaw:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomEventGetParams{\n\t\t\tRoomID: "!636q39766251:matrix.org",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", event.EventID)\n}\n', }, cli: { - method: 'reminders create', + method: 'events retrieve', example: - "beeper-desktop-cli chats:reminders create \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --reminder \"{remindAt: '2025-08-31T23:30:12.520Z'}\"", + "beeper-desktop-cli matrix:rooms:events retrieve \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:matrix.org' \\\n --event-id '$asfDuShaf7Gafaw:matrix.org'", }, php: { - method: 'chats->reminders->create', + method: 'matrix->rooms->events->retrieve', example: - "chats->reminders->create(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reminder: [\n 'remindAt' => new \\DateTimeImmutable('2025-08-31T23:30:12.520Z'),\n 'dismissOnIncomingMessage' => true,\n ],\n);\n\nvar_dump($result);", + "matrix->rooms->events->retrieve(\n '$asfDuShaf7Gafaw:matrix.org', roomID: '!636q39766251:matrix.org'\n);\n\nvar_dump($event);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/reminders \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reminder": {\n "remindAt": "2025-08-31T23:30:12.520Z"\n }\n }\'', + 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/event/$EVENT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'delete', - endpoint: '/v1/chats/{chatID}/reminders', - httpMethod: 'delete', - summary: 'Delete a chat reminder', - description: 'Clear an existing reminder from a chat', - stainlessPath: '(resource) chats.reminders > (method) delete', - qualified: 'client.chats.reminders.delete', - params: ['chatID: string;'], + name: 'whoami', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami', + httpMethod: 'get', + summary: 'Get info about the bridge and your logins.', + description: + 'Get all info that is useful for presenting this bridge in a manager interface.\n* Server details: remote network details, available login flows, homeserver name, bridge bot user ID, command prefix\n* User details: management room ID, list of logins with current state and info\n', + stainlessPath: '(resource) matrix.bridges.auth > (method) whoami', + qualified: 'client.matrix.bridges.auth.whoami', + params: ['bridgeID: string;'], + response: + "{ bridge_bot: string; command_prefix: string; homeserver: string; login_flows: { id: string; description: string; name: string; }[]; logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]; network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }; management_room?: string; }", markdown: - "## delete\n\n`client.chats.reminders.delete(chatID: string): void`\n\n**delete** `/v1/chats/{chatID}/reminders`\n\nClear an existing reminder from a chat\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", + "## whoami\n\n`client.matrix.bridges.auth.whoami(bridgeID: string): { bridge_bot: string; command_prefix: string; homeserver: string; login_flows: object[]; logins: object[]; network: object; management_room?: string; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami`\n\nGet all info that is useful for presenting this bridge in a manager interface.\n* Server details: remote network details, available login flows, homeserver name, bridge bot user ID, command prefix\n* User details: management room ID, list of logins with current state and info\n\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ bridge_bot: string; command_prefix: string; homeserver: string; login_flows: { id: string; description: string; name: string; }[]; logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]; network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }; management_room?: string; }`\n Info about the bridge and user\n\n - `bridge_bot: string`\n - `command_prefix: string`\n - `homeserver: string`\n - `login_flows: { id: string; description: string; name: string; }[]`\n - `logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]`\n - `network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }`\n - `management_room?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.whoami('bridgeID');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.chats.reminders.delete', + method: 'client.matrix.bridges.auth.whoami', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com');", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.whoami('bridgeID');\n\nconsole.log(response.bridge_bot);", }, python: { - method: 'chats.reminders.delete', + method: 'matrix.bridges.auth.whoami', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.reminders.delete(\n "!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.whoami(\n "bridgeID",\n)\nprint(response.bridge_bot)', }, go: { - method: 'client.Chats.Reminders.Delete', + method: 'client.Matrix.Bridges.Auth.Whoami', example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.Delete(context.TODO(), "!NCdzlIaMjZUmvmvyHU:beeper.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.Whoami(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.BridgeBot)\n}\n', }, cli: { - method: 'reminders delete', + method: 'auth whoami', example: - "beeper-desktop-cli chats:reminders delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:bridges:auth whoami \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", }, php: { - method: 'chats->reminders->delete', + method: 'matrix->bridges->auth->whoami', example: - "chats->reminders->delete('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nvar_dump($result);", + "matrix->bridges->auth->whoami('bridgeID');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/reminders \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/whoami \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'add', - endpoint: '/v1/chats/{chatID}/messages/{messageID}/reactions', - httpMethod: 'post', - summary: 'Add a reaction', - description: 'Add a reaction to an existing message.', - stainlessPath: '(resource) chats.messages.reactions > (method) add', - qualified: 'client.chats.messages.reactions.add', - params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;', 'transactionID?: string;'], - response: - '{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }', + name: 'list_flows', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows', + httpMethod: 'get', + summary: 'Get the available login flows.', + description: 'Get the available login flows.', + stainlessPath: '(resource) matrix.bridges.auth > (method) list_flows', + qualified: 'client.matrix.bridges.auth.listFlows', + params: ['bridgeID: string;'], + response: '{ flows?: { id: string; description: string; name: string; }[]; }', markdown: - "## add\n\n`client.chats.messages.reactions.add(chatID: string, messageID: string, reactionKey: string, transactionID?: string): { chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n**post** `/v1/chats/{chatID}/messages/{messageID}/reactions`\n\nAdd a reaction to an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to add (emoji, shortcode, or custom emoji key)\n\n- `transactionID?: string`\n Optional transaction ID for deduplication and send tracking\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n - `transactionID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.messages.reactions.add('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', reactionKey: 'x' });\n\nconsole.log(response);\n```", + "## list_flows\n\n`client.matrix.bridges.auth.listFlows(bridgeID: string): { flows?: object[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows`\n\nGet the available login flows.\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ flows?: { id: string; description: string; name: string; }[]; }`\n\n - `flows?: { id: string; description: string; name: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.listFlows('bridgeID');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.chats.messages.reactions.add', + method: 'client.matrix.bridges.auth.listFlows', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.chats.messages.reactions.add('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reactionKey: 'x',\n});\n\nconsole.log(response.chatID);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.listFlows('bridgeID');\n\nconsole.log(response.flows);", }, python: { - method: 'chats.messages.reactions.add', + method: 'matrix.bridges.auth.list_flows', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.chats.messages.reactions.add(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n reaction_key="x",\n)\nprint(response.chat_id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.list_flows(\n "bridgeID",\n)\nprint(response.flows)', }, go: { - method: 'client.Chats.Messages.Reactions.Add', + method: 'client.Matrix.Bridges.Auth.ListFlows', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Messages.Reactions.Add(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.ChatMessageReactionAddParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tReactionKey: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ChatID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.ListFlows(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Flows)\n}\n', }, cli: { - method: 'reactions add', + method: 'auth list_flows', example: - "beeper-desktop-cli chats:messages:reactions add \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", + "beeper-desktop-cli matrix:bridges:auth list-flows \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", }, php: { - method: 'chats->messages->reactions->add', + method: 'matrix->bridges->auth->listFlows', example: - "chats->messages->reactions->add(\n '1343993',\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reactionKey: 'x',\n transactionID: 'transactionID',\n);\n\nvar_dump($response);", + "matrix->bridges->auth->listFlows('bridgeID');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID/reactions \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reactionKey": "x"\n }\'', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/flows \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'delete', - endpoint: '/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}', - httpMethod: 'delete', - summary: 'Remove a reaction', - description: 'Remove the reaction added by the authenticated user from an existing message.', - stainlessPath: '(resource) chats.messages.reactions > (method) delete', - qualified: 'client.chats.messages.reactions.delete', - params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;'], - response: '{ chatID: string; messageID: string; reactionKey: string; success: true; }', + name: 'list_logins', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins', + httpMethod: 'get', + summary: 'Get the login IDs of the current user.', + description: 'Get the login IDs of the current user.', + stainlessPath: '(resource) matrix.bridges.auth > (method) list_logins', + qualified: 'client.matrix.bridges.auth.listLogins', + params: ['bridgeID: string;'], + response: '{ login_ids?: string[]; }', markdown: - "## delete\n\n`client.chats.messages.reactions.delete(chatID: string, messageID: string, reactionKey: string): { chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}`\n\nRemove the reaction added by the authenticated user from an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to remove (emoji, shortcode, or custom emoji key)\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reaction = await client.chats.messages.reactions.delete('x', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993' });\n\nconsole.log(reaction);\n```", + "## list_logins\n\n`client.matrix.bridges.auth.listLogins(bridgeID: string): { login_ids?: string[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins`\n\nGet the login IDs of the current user.\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ login_ids?: string[]; }`\n\n - `login_ids?: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.listLogins('bridgeID');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.chats.messages.reactions.delete', + method: 'client.matrix.bridges.auth.listLogins', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reaction = await client.chats.messages.reactions.delete('x', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n messageID: '1343993',\n});\n\nconsole.log(reaction.chatID);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.listLogins('bridgeID');\n\nconsole.log(response.login_ids);", }, python: { - method: 'chats.messages.reactions.delete', + method: 'matrix.bridges.auth.list_logins', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreaction = client.chats.messages.reactions.delete(\n reaction_key="x",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n message_id="1343993",\n)\nprint(reaction.chat_id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.list_logins(\n "bridgeID",\n)\nprint(response.login_ids)', }, go: { - method: 'client.Chats.Messages.Reactions.Delete', + method: 'client.Matrix.Bridges.Auth.ListLogins', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treaction, err := client.Chats.Messages.Reactions.Delete(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.ChatMessageReactionDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tMessageID: "1343993",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reaction.ChatID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.ListLogins(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.LoginIDs)\n}\n', }, cli: { - method: 'reactions delete', + method: 'auth list_logins', example: - "beeper-desktop-cli chats:messages:reactions delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", + "beeper-desktop-cli matrix:bridges:auth list-logins \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", }, php: { - method: 'chats->messages->reactions->delete', + method: 'matrix->bridges->auth->listLogins', example: - "chats->messages->reactions->delete(\n 'x', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($reaction);", + "matrix->bridges->auth->listLogins('bridgeID');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID/reactions/$REACTION_KEY \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/logins \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'search', - endpoint: '/v1/messages/search', - httpMethod: 'get', - summary: 'Search messages', - description: 'Search messages across chats.', - stainlessPath: '(resource) messages > (method) search', - qualified: 'client.messages.search', - params: [ - 'accountIDs?: string[];', - 'chatIDs?: string[];', - "chatType?: 'group' | 'single';", - 'cursor?: string;', - 'dateAfter?: string;', - 'dateBefore?: string;', - "direction?: 'after' | 'before';", - 'excludeLowPriority?: boolean;', - 'includeMuted?: boolean;', - 'limit?: number;', - "mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[];", - 'query?: string;', - 'sender?: string;', - ], + name: 'start_login', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}', + httpMethod: 'post', + summary: 'Start a new login process.', + description: + "This endpoint starts a new login process, which is used to log into the bridge.\n\nThe basic flow of the entire login, including calling this endpoint, is:\n1. Call `GET /v3/login/flows` to get the list of available flows.\n If there's more than one flow, ask the user to pick which one they want to use.\n2. Call this endpoint with the chosen flow ID to start the login.\n The first login step will be returned.\n3. Render the information provided in the step.\n4. Call the `/login/step/...` endpoint corresponding to the step type:\n * For `user_input` and `cookies`, acquire the requested fields before calling the endpoint.\n * For `display_and_wait`, call the endpoint immediately\n (as there's nothing to acquire on the client side).\n5. Handle the data returned by the login step endpoint:\n * If an error is returned, the login has failed and must be restarted\n (from either step 1 or step 2) if the user wants to try again.\n * If step type `complete` is returned, the login finished successfully.\n * Otherwise, go to step 3 with the new data.\n", + stainlessPath: '(resource) matrix.bridges.auth > (method) start_login', + qualified: 'client.matrix.bridges.auth.startLogin', + params: ['bridgeID: string;', 'flowID: string;', 'login_id?: string;'], response: - "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", + "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", markdown: - "## search\n\n`client.messages.search(accountIDs?: string[], chatIDs?: string[], chatType?: 'group' | 'single', cursor?: string, dateAfter?: string, dateBefore?: string, direction?: 'after' | 'before', excludeLowPriority?: boolean, includeMuted?: boolean, limit?: number, mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[], query?: string, sender?: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/messages/search`\n\nSearch messages across chats.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit search to specific account IDs.\n\n- `chatIDs?: string[]`\n Limit search to specific chat IDs.\n\n- `chatType?: 'group' | 'single'`\n Filter by chat type: 'group' for group chats, 'single' for 1:1 chats.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `dateAfter?: string`\n Only include messages with timestamp strictly after this ISO 8601 datetime (e.g., '2024-07-01T00:00:00Z' or '2024-07-01T00:00:00+02:00').\n\n- `dateBefore?: string`\n Only include messages with timestamp strictly before this ISO 8601 datetime (e.g., '2024-07-31T23:59:59Z' or '2024-07-31T23:59:59+02:00').\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `excludeLowPriority?: boolean`\n Exclude messages marked Low Priority by the user. Default: true. Set to false to include all.\n\n- `includeMuted?: boolean`\n Include messages in 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.\n\n- `limit?: number`\n Maximum number of messages to return.\n\n- `mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[]`\n Filter messages by media types. Use ['any'] for any media type, or specify exact types like ['video', 'image']. Omit for no media filtering.\n\n- `query?: string`\n Literal word search (non-semantic). Finds messages containing these EXACT words in any order. Use single words users actually type, not concepts or phrases. Example: use \"dinner\" not \"dinner plans\", use \"sick\" not \"health issues\". If omitted, returns results filtered only by other parameters.\n\n- `sender?: string`\n Filter by sender: 'me' (messages sent by the authenticated user), 'others' (messages sent by others), or a specific user ID string (user.id).\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message);\n}\n```", + "## start_login\n\n`client.matrix.bridges.auth.startLogin(bridgeID: string, flowID: string, login_id?: string): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}`\n\nThis endpoint starts a new login process, which is used to log into the bridge.\n\nThe basic flow of the entire login, including calling this endpoint, is:\n1. Call `GET /v3/login/flows` to get the list of available flows.\n If there's more than one flow, ask the user to pick which one they want to use.\n2. Call this endpoint with the chosen flow ID to start the login.\n The first login step will be returned.\n3. Render the information provided in the step.\n4. Call the `/login/step/...` endpoint corresponding to the step type:\n * For `user_input` and `cookies`, acquire the requested fields before calling the endpoint.\n * For `display_and_wait`, call the endpoint immediately\n (as there's nothing to acquire on the client side).\n5. Handle the data returned by the login step endpoint:\n * If an error is returned, the login has failed and must be restarted\n (from either step 1 or step 2) if the user wants to try again.\n * If step type `complete` is returned, the login finished successfully.\n * Otherwise, go to step 3 with the new data.\n\n\n### Parameters\n\n- `bridgeID: string`\n\n- `flowID: string`\n\n- `login_id?: string`\n An existing login ID to re-login as. If this is specified and the user logs into a different account, the provided ID will be logged out.\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.messages.search', + method: 'client.matrix.bridges.auth.startLogin', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message.id);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' });\n\nconsole.log(response);", }, python: { - method: 'messages.search', + method: 'matrix.bridges.auth.start_login', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.messages.search()\npage = page.items[0]\nprint(page.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.start_login(\n flow_id="qr",\n bridge_id="bridgeID",\n)\nprint(response)', }, go: { - method: 'client.Messages.Search', + method: 'client.Matrix.Bridges.Auth.StartLogin', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.Search(context.TODO(), beeperdesktopapi.MessageSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.StartLogin(\n\t\tcontext.TODO(),\n\t\t"qr",\n\t\tbeeperdesktopapi.MatrixBridgeAuthStartLoginParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'messages search', - example: "beeper-desktop-cli messages search \\\n --access-token 'My Access Token'", + method: 'auth start_login', + example: + "beeper-desktop-cli matrix:bridges:auth start-login \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --flow-id qr", }, php: { - method: 'messages->search', + method: 'matrix->bridges->auth->startLogin', example: - "messages->search(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n chatIDs: ['!NCdzlIaMjZUmvmvyHU:beeper.com', '1231073'],\n chatType: 'group',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n dateAfter: new \\DateTimeImmutable('2025-08-01T00:00:00Z'),\n dateBefore: new \\DateTimeImmutable('2025-08-31T23:59:59Z'),\n direction: 'before',\n excludeLowPriority: true,\n includeMuted: true,\n limit: 20,\n mediaTypes: ['any'],\n query: 'dinner',\n sender: 'sender',\n);\n\nvar_dump($page);", + "matrix->bridges->auth->startLogin(\n 'qr', bridgeID: 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/messages/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/start/$FLOW_ID \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'list', - endpoint: '/v1/chats/{chatID}/messages', - httpMethod: 'get', - summary: 'List messages', - description: 'List all messages in a chat with cursor-based pagination. Sorted by timestamp.', - stainlessPath: '(resource) messages > (method) list', - qualified: 'client.messages.list', - params: ['chatID: string;', 'cursor?: string;', "direction?: 'after' | 'before';"], + name: 'submit_user_input', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input', + httpMethod: 'post', + summary: 'Submit user input in a login process.', + description: 'Submit user input in a login process.', + stainlessPath: '(resource) matrix.bridges.auth > (method) submit_user_input', + qualified: 'client.matrix.bridges.auth.submitUserInput', + params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;', 'body: object;'], response: - "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", + "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", markdown: - "## list\n\n`client.messages.list(chatID: string, cursor?: string, direction?: 'after' | 'before'): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages`\n\nList all messages in a chat with cursor-based pagination. Sorted by timestamp.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message);\n}\n```", + "## submit_user_input\n\n`client.matrix.bridges.auth.submitUserInput(bridgeID: string, loginProcessID: string, stepID: string, body: object): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input`\n\nSubmit user input in a login process.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n- `body: object`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.submitUserInput('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.messages.list', + method: 'client.matrix.bridges.auth.submitUserInput', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message.id);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.submitUserInput('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);", }, python: { - method: 'messages.list', + method: 'matrix.bridges.auth.submit_user_input', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.messages.list(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\npage = page.items[0]\nprint(page.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.submit_user_input(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n body={\n "foo": "string"\n },\n)\nprint(response)', }, go: { - method: 'client.Messages.List', + method: 'client.Matrix.Bridges.Auth.SubmitUserInput', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.List(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.SubmitUserInput(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthSubmitUserInputParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t\tBody: map[string]string{\n\t\t\t\t"foo": "string",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'messages list', + method: 'auth submit_user_input', example: - "beeper-desktop-cli messages list \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:bridges:auth submit-user-input \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID \\\n --body '{foo: string}'", }, php: { - method: 'messages->list', + method: 'matrix->bridges->auth->submitUserInput', example: - "messages->list(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n);\n\nvar_dump($page);", + "matrix->bridges->auth->submitUserInput(\n 'stepID',\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: ['foo' => 'string'],\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/user_input \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "foo": "string"\n }\'', }, }, }, { - name: 'send', - endpoint: '/v1/chats/{chatID}/messages', + name: 'submit_cookies', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies', httpMethod: 'post', - summary: 'Send a message', - description: - 'Send a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.', - stainlessPath: '(resource) messages > (method) send', - qualified: 'client.messages.send', - params: [ - 'chatID: string;', - "attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; };", - 'replyToMessageID?: string;', - 'text?: string;', - ], - response: '{ chatID: string; pendingMessageID: string; }', + summary: 'Submit extracted cookies in a login process.', + description: 'Submit extracted cookies in a login process.', + stainlessPath: '(resource) matrix.bridges.auth > (method) submit_cookies', + qualified: 'client.matrix.bridges.auth.submitCookies', + params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;', 'body: object;'], + response: + "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", markdown: - "## send\n\n`client.messages.send(chatID: string, attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }, replyToMessageID?: string, text?: string): { chatID: string; pendingMessageID: string; }`\n\n**post** `/v1/chats/{chatID}/messages`\n\nSend a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }`\n Single attachment to send with the message\n - `uploadID: string`\n Upload ID from uploadAsset endpoint. Required to reference uploaded files.\n - `duration?: number`\n Duration in seconds (optional override of cached value)\n - `fileName?: string`\n Filename (optional override of cached value)\n - `mimeType?: string`\n MIME type (optional override of cached value)\n - `size?: { height: number; width: number; }`\n Dimensions (optional override of cached value)\n - `type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'`\n Attachment type hint (image, video, audio, file, gif, voice-note, sticker). If omitted, auto-detected from mimeType\n\n- `replyToMessageID?: string`\n Provide a message ID to send this as a reply to an existing message\n\n- `text?: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n\n### Returns\n\n- `{ chatID: string; pendingMessageID: string; }`\n\n - `chatID: string`\n - `pendingMessageID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response);\n```", + "## submit_cookies\n\n`client.matrix.bridges.auth.submitCookies(bridgeID: string, loginProcessID: string, stepID: string, body: object): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies`\n\nSubmit extracted cookies in a login process.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n- `body: object`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.submitCookies('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.messages.send', + method: 'client.matrix.bridges.auth.submitCookies', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response.pendingMessageID);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.submitCookies('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);", }, python: { - method: 'messages.send', + method: 'matrix.bridges.auth.submit_cookies', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.messages.send(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(response.pending_message_id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.submit_cookies(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n body={\n "foo": "string"\n },\n)\nprint(response)', }, go: { - method: 'client.Messages.Send', + method: 'client.Matrix.Bridges.Auth.SubmitCookies', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Messages.Send(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageSendParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.PendingMessageID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.SubmitCookies(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthSubmitCookiesParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t\tBody: map[string]string{\n\t\t\t\t"foo": "string",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'messages send', + method: 'auth submit_cookies', example: - "beeper-desktop-cli messages send \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop-cli matrix:bridges:auth submit-cookies \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID \\\n --body '{foo: string}'", }, php: { - method: 'messages->send', + method: 'matrix->bridges->auth->submitCookies', example: - "messages->send(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n attachment: [\n 'uploadID' => 'uploadID',\n 'duration' => 0,\n 'fileName' => 'fileName',\n 'mimeType' => 'mimeType',\n 'size' => ['height' => 0, 'width' => 0],\n 'type' => 'image',\n ],\n replyToMessageID: 'replyToMessageID',\n text: 'text',\n);\n\nvar_dump($response);", + "matrix->bridges->auth->submitCookies(\n 'stepID',\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: ['foo' => 'string'],\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/cookies \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "foo": "string"\n }\'', }, }, }, { - name: 'retrieve', - endpoint: '/v1/chats/{chatID}/messages/{messageID}', - httpMethod: 'get', - summary: 'Retrieve a message', - description: - 'Retrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.', - stainlessPath: '(resource) messages > (method) retrieve', - qualified: 'client.messages.retrieve', - params: ['chatID: string;', 'messageID: string;'], + name: 'wait_for_step', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait', + httpMethod: 'post', + summary: 'Wait for the next step after displaying data to the user.', + description: 'Wait for the next step after displaying data to the user.', + stainlessPath: '(resource) matrix.bridges.auth > (method) wait_for_step', + qualified: 'client.matrix.bridges.auth.waitForStep', + params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;'], response: - "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", + "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", markdown: - "## retrieve\n\n`client.messages.retrieve(chatID: string, messageID: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages/{messageID}`\n\nRetrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.retrieve('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });\n\nconsole.log(message);\n```", + "## wait_for_step\n\n`client.matrix.bridges.auth.waitForStep(bridgeID: string, loginProcessID: string, stepID: string): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait`\n\nWait for the next step after displaying data to the user.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.waitForStep('stepID', { bridgeID: 'bridgeID', loginProcessID: 'loginProcessID' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.messages.retrieve', + method: 'client.matrix.bridges.auth.waitForStep', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst message = await client.messages.retrieve('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n});\n\nconsole.log(message.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.waitForStep('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n});\n\nconsole.log(response);", }, python: { - method: 'messages.retrieve', + method: 'matrix.bridges.auth.wait_for_step', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nmessage = client.messages.retrieve(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(message.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.wait_for_step(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n)\nprint(response)', }, go: { - method: 'client.Messages.Get', + method: 'client.Matrix.Bridges.Auth.WaitForStep', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Get(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageGetParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.WaitForStep(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthWaitForStepParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'messages retrieve', + method: 'auth wait_for_step', example: - "beeper-desktop-cli messages retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", + "beeper-desktop-cli matrix:bridges:auth wait-for-step \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID", }, php: { - method: 'messages->retrieve', + method: 'matrix->bridges->auth->waitForStep', example: - "messages->retrieve(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com'\n);\n\nvar_dump($message);", + "matrix->bridges->auth->waitForStep(\n 'stepID', bridgeID: 'bridgeID', loginProcessID: 'loginProcessID'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/display_and_wait \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'update', - endpoint: '/v1/chats/{chatID}/messages/{messageID}', - httpMethod: 'put', - summary: 'Edit a message', - description: 'Edit the text content of an existing message. Messages with attachments cannot be edited.', - stainlessPath: '(resource) messages > (method) update', - qualified: 'client.messages.update', - params: ['chatID: string;', 'messageID: string;', 'text: string;'], - response: - "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", + name: 'logout', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}', + httpMethod: 'post', + summary: 'Log out of an existing login.', + description: 'Log out of an existing login.', + stainlessPath: '(resource) matrix.bridges.auth > (method) logout', + qualified: 'client.matrix.bridges.auth.logout', + params: ['bridgeID: string;', 'loginID: string;'], + response: 'object', markdown: - "## update\n\n`client.messages.update(chatID: string, messageID: string, text: string): object`\n\n**put** `/v1/chats/{chatID}/messages/{messageID}`\n\nEdit the text content of an existing message. Messages with attachments cannot be edited.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `text: string`\n New text content for the message\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.update('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x' });\n\nconsole.log(message);\n```", + "## logout\n\n`client.matrix.bridges.auth.logout(bridgeID: string, loginID: string): object`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}`\n\nLog out of an existing login.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginID: string`\n The unique ID of a login. Defined by the network connector.\n\n### Returns\n\n- `object`\n Empty object\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.messages.update', + method: 'client.matrix.bridges.auth.logout', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst message = await client.messages.update('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n text: 'x',\n});\n\nconsole.log(message);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', {\n bridgeID: 'bridgeID',\n});\n\nconsole.log(response);", }, python: { - method: 'messages.update', + method: 'matrix.bridges.auth.logout', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nmessage = client.messages.update(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n text="x",\n)\nprint(message)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.logout(\n login_id="bcc68892-b180-414f-9516-b4aadf7d0496",\n bridge_id="bridgeID",\n)\nprint(response)', }, go: { - method: 'client.Messages.Update', + method: 'client.Matrix.Bridges.Auth.Logout', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Update(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageUpdateParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tText: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.Logout(\n\t\tcontext.TODO(),\n\t\t"bcc68892-b180-414f-9516-b4aadf7d0496",\n\t\tbeeperdesktopapi.MatrixBridgeAuthLogoutParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'messages update', + method: 'auth logout', example: - "beeper-desktop-cli messages update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --text x", + "beeper-desktop-cli matrix:bridges:auth logout \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-id bcc68892-b180-414f-9516-b4aadf7d0496", }, php: { - method: 'messages->update', + method: 'matrix->bridges->auth->logout', example: - "messages->update(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x'\n);\n\nvar_dump($message);", + "matrix->bridges->auth->logout(\n 'bcc68892-b180-414f-9516-b4aadf7d0496', bridgeID: 'bridgeID'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "text": "x"\n }\'', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/logout/$LOGIN_ID \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'delete', - endpoint: '/v1/chats/{chatID}/messages/{messageID}', - httpMethod: 'delete', - summary: 'Delete a message', - description: - 'Delete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.', - stainlessPath: '(resource) messages > (method) delete', - qualified: 'client.messages.delete', - params: ['chatID: string;', 'messageID: string;', 'forEveryone?: boolean;'], + name: 'list', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts', + httpMethod: 'get', + summary: 'Get a list of contacts.', + description: 'Get a list of contacts.', + stainlessPath: '(resource) matrix.bridges.contacts > (method) list', + qualified: 'client.matrix.bridges.contacts.list', + params: ['bridgeID: string;', 'login_id?: string;'], + response: + '{ contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }', markdown: - "## delete\n\n`client.messages.delete(chatID: string, messageID: string, forEveryone?: boolean): void`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}`\n\nDelete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `forEveryone?: boolean`\n True to request deletion for everyone when the network supports it; false to delete only for the authenticated user when supported.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' })\n```", + "## list\n\n`client.matrix.bridges.contacts.list(bridgeID: string, login_id?: string): { contacts?: object[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts`\n\nGet a list of contacts.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }`\n\n - `contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst contacts = await client.matrix.bridges.contacts.list('bridgeID');\n\nconsole.log(contacts);\n```", perLanguage: { typescript: { - method: 'client.messages.delete', + method: 'client.matrix.bridges.contacts.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst contacts = await client.matrix.bridges.contacts.list('bridgeID');\n\nconsole.log(contacts.contacts);", }, python: { - method: 'messages.delete', + method: 'matrix.bridges.contacts.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.messages.delete(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\ncontacts = client.matrix.bridges.contacts.list(\n bridge_id="bridgeID",\n)\nprint(contacts.contacts)', }, go: { - method: 'client.Messages.Delete', + method: 'client.Matrix.Bridges.Contacts.List', example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Messages.Delete(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tcontacts, err := client.Matrix.Bridges.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"bridgeID",\n\t\tbeeperdesktopapi.MatrixBridgeContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", contacts.Contacts)\n}\n', }, cli: { - method: 'messages delete', + method: 'contacts list', example: - "beeper-desktop-cli messages delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", + "beeper-desktop-cli matrix:bridges:contacts list \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", }, php: { - method: 'messages->delete', + method: 'matrix->bridges->contacts->list', example: - "messages->delete(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', forEveryone: true\n);\n\nvar_dump($result);", + "matrix->bridges->contacts->list(\n 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496'\n);\n\nvar_dump($contacts);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/contacts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'download', - endpoint: '/v1/assets/download', + name: 'search', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users', httpMethod: '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.', - stainlessPath: '(resource) assets > (method) download', - qualified: 'client.assets.download', - params: ['url: string;'], - response: '{ error?: string; srcURL?: string; }', + summary: 'Search for users on the remote network', + description: 'Search for users on the remote network', + stainlessPath: '(resource) matrix.bridges.users > (method) search', + qualified: 'client.matrix.bridges.users.search', + params: ['bridgeID: string;', 'login_id?: string;', 'query?: string;'], + response: + '{ results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }', markdown: - "## download\n\n`client.assets.download(url: string): { error?: string; srcURL?: string; }`\n\n**post** `/v1/assets/download`\n\nDownload a Matrix file using its mxc:// or localmxc:// URL to the device running Beeper Desktop and return the local file URL.\n\n### Parameters\n\n- `url: string`\n Matrix content URL (mxc:// or localmxc://) for the file to download.\n\n### Returns\n\n- `{ error?: string; srcURL?: string; }`\n\n - `error?: string`\n - `srcURL?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response);\n```", + "## search\n\n`client.matrix.bridges.users.search(bridgeID: string, login_id?: string, query?: string): { results?: object[]; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users`\n\nSearch for users on the remote network\n\n### Parameters\n\n- `bridgeID: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n- `query?: string`\n The search query to send to the remote network\n\n### Returns\n\n- `{ results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }`\n\n - `results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.users.search('bridgeID');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.assets.download', + method: 'client.matrix.bridges.users.search', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response.error);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.users.search('bridgeID');\n\nconsole.log(response.results);", }, python: { - method: 'assets.download', + method: 'matrix.bridges.users.search', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.download(\n url="mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n)\nprint(response.error)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.users.search(\n bridge_id="bridgeID",\n)\nprint(response.results)', }, go: { - method: 'client.Assets.Download', + method: 'client.Matrix.Bridges.Users.Search', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Download(context.TODO(), beeperdesktopapi.AssetDownloadParams{\n\t\tURL: "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Error)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Users.Search(\n\t\tcontext.TODO(),\n\t\t"bridgeID",\n\t\tbeeperdesktopapi.MatrixBridgeUserSearchParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Results)\n}\n', }, cli: { - method: 'assets download', + method: 'users search', example: - "beeper-desktop-cli assets download \\\n --access-token 'My Access Token' \\\n --url mxc://example.org/Q4x9CqGz1pB3Oa6XgJ", + "beeper-desktop-cli matrix:bridges:users search \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", }, php: { - method: 'assets->download', + method: 'matrix->bridges->users->search', example: - "assets->download(\n url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ'\n);\n\nvar_dump($response);", + "matrix->bridges->users->search(\n 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496', query: 'query'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/assets/download \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "url": "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ"\n }\'', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/search_users \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'upload', - endpoint: '/v1/assets/upload', - httpMethod: '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.', - stainlessPath: '(resource) assets > (method) upload', - qualified: 'client.assets.upload', - params: ['file: string;', 'fileName?: string;', 'mimeType?: string;'], + name: 'resolve', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}', + httpMethod: 'get', + summary: 'Resolve an identifier to a user on the remote network.', + description: 'Resolve an identifier to a user on the remote network.', + stainlessPath: '(resource) matrix.bridges.users > (method) resolve', + qualified: 'client.matrix.bridges.users.resolve', + params: ['bridgeID: string;', 'identifier: string;', 'login_id?: string;'], response: - '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', + '{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }', markdown: - "## upload\n\n`client.assets.upload(file: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload`\n\nUpload 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.\n\n### Parameters\n\n- `file: string`\n The file to upload (max 500 MB).\n\n- `fileName?: string`\n Original filename. Defaults to the uploaded file name if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response);\n```", + "## resolve\n\n`client.matrix.bridges.users.resolve(bridgeID: string, identifier: string, login_id?: string): { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}`\n\nResolve an identifier to a user on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `identifier: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n A successfully resolved identifier.\n\n - `id: string`\n - `avatar_url?: string`\n - `dm_room_mxid?: string`\n - `identifiers?: string[]`\n - `mxid?: string`\n - `name?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.assets.upload', + method: 'client.matrix.bridges.users.resolve', example: - "import fs from 'fs';\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response.width);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response.id);", }, python: { - method: 'assets.upload', + method: 'matrix.bridges.users.resolve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.upload(\n file=b"Example data",\n)\nprint(response.width)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.users.resolve(\n identifier="identifier",\n bridge_id="bridgeID",\n)\nprint(response.id)', }, go: { - method: 'client.Assets.Upload', + method: 'client.Matrix.Bridges.Users.Resolve', example: - 'package main\n\nimport (\n\t"bytes"\n\t"context"\n\t"fmt"\n\t"io"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Upload(context.TODO(), beeperdesktopapi.AssetUploadParams{\n\t\tFile: io.Reader(bytes.NewBuffer([]byte("Example data"))),\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Users.Resolve(\n\t\tcontext.TODO(),\n\t\t"identifier",\n\t\tbeeperdesktopapi.MatrixBridgeUserResolveParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', }, cli: { - method: 'assets upload', + method: 'users resolve', example: - "beeper-desktop-cli assets upload \\\n --access-token 'My Access Token' \\\n --file 'Example data'", + "beeper-desktop-cli matrix:bridges:users resolve \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --identifier identifier", }, php: { - method: 'assets->upload', + method: 'matrix->bridges->users->resolve', example: - "assets->upload(\n file: FileParam::fromString('Example data', filename: uniqid('file-upload-', true)),\n fileName: 'fileName',\n mimeType: 'mimeType',\n);\n\nvar_dump($response);", + "matrix->bridges->users->resolve(\n 'identifier',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n);\n\nvar_dump($response);", }, http: { example: - "curl http://localhost:23373/v1/assets/upload \\\n -H 'Content-Type: multipart/form-data' \\\n -H \"Authorization: Bearer $BEEPER_ACCESS_TOKEN\" \\\n -F 'file=@/path/to/file'", + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/resolve_identifier/$IDENTIFIER \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'upload_base64', - endpoint: '/v1/assets/upload/base64', + name: 'create_dm', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}', httpMethod: '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.', - stainlessPath: '(resource) assets > (method) upload_base64', - qualified: 'client.assets.uploadBase64', - params: ['content: string;', 'fileName?: string;', 'mimeType?: string;'], + summary: 'Create a direct chat with a user on the remote network.', + description: 'Create a direct chat with a user on the remote network.', + stainlessPath: '(resource) matrix.bridges.rooms > (method) create_dm', + qualified: 'client.matrix.bridges.rooms.createDm', + params: ['bridgeID: string;', 'identifier: string;', 'login_id?: string;'], response: - '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', + '{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }', markdown: - "## upload_base64\n\n`client.assets.uploadBase64(content: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload/base64`\n\nUpload 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.\n\n### Parameters\n\n- `content: string`\n Base64-encoded file content (max ~500MB decoded)\n\n- `fileName?: string`\n Original filename. Generated if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response);\n```", + "## create_dm\n\n`client.matrix.bridges.rooms.createDm(bridgeID: string, identifier: string, login_id?: string): { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}`\n\nCreate a direct chat with a user on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `identifier: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n A successfully resolved identifier.\n\n - `id: string`\n - `avatar_url?: string`\n - `dm_room_mxid?: string`\n - `identifiers?: string[]`\n - `mxid?: string`\n - `name?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.assets.uploadBase64', + method: 'client.matrix.bridges.rooms.createDm', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response.width);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response.id);", }, python: { - method: 'assets.upload_base64', + method: 'matrix.bridges.rooms.create_dm', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.upload_base64(\n content="x",\n)\nprint(response.width)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.rooms.create_dm(\n identifier="identifier",\n bridge_id="bridgeID",\n)\nprint(response.id)', }, go: { - method: 'client.Assets.UploadBase64', + method: 'client.Matrix.Bridges.Rooms.NewDm', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.UploadBase64(context.TODO(), beeperdesktopapi.AssetUploadBase64Params{\n\t\tContent: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Rooms.NewDm(\n\t\tcontext.TODO(),\n\t\t"identifier",\n\t\tbeeperdesktopapi.MatrixBridgeRoomNewDmParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', }, cli: { - method: 'assets upload_base64', + method: 'rooms create_dm', example: - "beeper-desktop-cli assets upload-base64 \\\n --access-token 'My Access Token' \\\n --content x", + "beeper-desktop-cli matrix:bridges:rooms create-dm \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --identifier identifier", }, php: { - method: 'assets->uploadBase64', + method: 'matrix->bridges->rooms->createDm', example: - "assets->uploadBase64(\n content: 'x', fileName: 'fileName', mimeType: 'mimeType'\n);\n\nvar_dump($response);", + "matrix->bridges->rooms->createDm(\n 'identifier',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/assets/upload/base64 \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "content": "x"\n }\'', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/create_dm/$IDENTIFIER \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'serve', - endpoint: '/v1/assets/serve', - httpMethod: '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.', - stainlessPath: '(resource) assets > (method) serve', - qualified: 'client.assets.serve', - params: ['url: string;'], - response: 'string', + name: 'create_group', + endpoint: + '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}', + httpMethod: 'post', + summary: 'Create a group chat on the remote network.', + description: 'Create a group chat on the remote network.', + stainlessPath: '(resource) matrix.bridges.rooms > (method) create_group', + qualified: 'client.matrix.bridges.rooms.createGroup', + params: [ + 'bridgeID: string;', + 'groupType: string;', + 'login_id?: string;', + 'avatar?: { url?: string; };', + 'disappear?: { timer?: number; type?: string; };', + 'name?: { name?: string; };', + 'parent?: object;', + 'participants?: string[];', + 'room_id?: string;', + 'topic?: { topic?: string; };', + 'type?: string;', + 'username?: string;', + ], + response: '{ id: string; mxid: string; }', markdown: - "## serve\n\n`client.assets.serve(url: string): string`\n\n**get** `/v1/assets/serve`\n\nStream a file given an mxc://, localmxc://, or file:// URL. Downloads first if not cached. Supports Range requests for seeking in large files.\n\n### Parameters\n\n- `url: string`\n File URL to serve. Accepts mxc://, localmxc://, or file:// URLs.\n\n### Returns\n\n- `string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.serve({ url: 'x' });\n\nconsole.log(response);\n\nconst content = await response.blob()\nconsole.log(content)\n```", + "## create_group\n\n`client.matrix.bridges.rooms.createGroup(bridgeID: string, groupType: string, login_id?: string, avatar?: { url?: string; }, disappear?: { timer?: number; type?: string; }, name?: { name?: string; }, parent?: object, participants?: string[], room_id?: string, topic?: { topic?: string; }, type?: string, username?: string): { id: string; mxid: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}`\n\nCreate a group chat on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `groupType: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n- `avatar?: { url?: string; }`\n The `m.room.avatar` event content for the room.\n - `url?: string`\n\n- `disappear?: { timer?: number; type?: string; }`\n The `com.beeper.disappearing_timer` event content for the room.\n - `timer?: number`\n - `type?: string`\n\n- `name?: { name?: string; }`\n The `m.room.name` event content for the room.\n - `name?: string`\n\n- `parent?: object`\n\n- `participants?: string[]`\n The users to add to the group initially.\n\n- `room_id?: string`\n An existing Matrix room ID to bridge to.\nThe other parameters must be already in sync with the room state when using this parameter.\n\n\n- `topic?: { topic?: string; }`\n The `m.room.topic` event content for the room.\n - `topic?: string`\n\n- `type?: string`\n The type of group to create.\n\n- `username?: string`\n The public username for the created group.\n\n### Returns\n\n- `{ id: string; mxid: string; }`\n A successfully created group chat.\n\n - `id: string`\n - `mxid: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.rooms.createGroup('groupType', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.assets.serve', + method: 'client.matrix.bridges.rooms.createGroup', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.serve({ url: 'x' });\n\nconsole.log(response);\n\nconst content = await response.blob();\nconsole.log(content);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.rooms.createGroup('groupType', {\n bridgeID: 'bridgeID',\n});\n\nconsole.log(response.id);", }, python: { - method: 'assets.serve', + method: 'matrix.bridges.rooms.create_group', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.serve(\n url="x",\n)\nprint(response)\ncontent = response.read()\nprint(content)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.rooms.create_group(\n group_type="groupType",\n bridge_id="bridgeID",\n)\nprint(response.id)', }, go: { - method: 'client.Assets.Serve', + method: 'client.Matrix.Bridges.Rooms.NewGroup', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Serve(context.TODO(), beeperdesktopapi.AssetServeParams{\n\t\tURL: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Rooms.NewGroup(\n\t\tcontext.TODO(),\n\t\t"groupType",\n\t\tbeeperdesktopapi.MatrixBridgeRoomNewGroupParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', }, cli: { - method: 'assets serve', - example: "beeper-desktop-cli assets serve \\\n --access-token 'My Access Token' \\\n --url x", + method: 'rooms create_group', + example: + "beeper-desktop-cli matrix:bridges:rooms create-group \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --group-type groupType", }, php: { - method: 'assets->serve', + method: 'matrix->bridges->rooms->createGroup', example: - "assets->serve(url: 'x');\n\nvar_dump($response);", + "matrix->bridges->rooms->createGroup(\n 'groupType',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n avatar: ['url' => 'url'],\n disappear: ['timer' => 0, 'type' => 'type'],\n name: ['name' => 'name'],\n parent: (object) [],\n participants: ['string'],\n roomID: 'room_id',\n topic: ['topic' => 'topic'],\n type: 'channel',\n username: 'username',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/assets/serve \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/create_group/$GROUP_TYPE \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { name: 'retrieve', - endpoint: '/v1/info', + endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities', httpMethod: 'get', - summary: 'Retrieve server info', - description: - 'Returns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.', - stainlessPath: '(resource) info > (method) retrieve', - qualified: 'client.info.retrieve', - response: - '{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }', + summary: 'Get bridge capabilities', + description: 'Get bridge capabilities', + stainlessPath: '(resource) matrix.bridges.capabilities > (method) retrieve', + qualified: 'client.matrix.bridges.capabilities.retrieve', + params: ['bridgeID: string;'], + response: 'object', markdown: - "## retrieve\n\n`client.info.retrieve(): { app: object; endpoints: object; platform: object; server: object; }`\n\n**get** `/v1/info`\n\nReturns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.\n\n### Returns\n\n- `{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }`\n\n - `app: { bundle_id: string; name: string; version: string; }`\n - `endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }`\n - `platform: { arch: string; os: string; release?: string; }`\n - `server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info);\n```", + "## retrieve\n\n`client.matrix.bridges.capabilities.retrieve(bridgeID: string): object`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities`\n\nGet bridge capabilities\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst capability = await client.matrix.bridges.capabilities.retrieve('bridgeID');\n\nconsole.log(capability);\n```", perLanguage: { typescript: { - method: 'client.info.retrieve', + method: 'client.matrix.bridges.capabilities.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info.app);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst capability = await client.matrix.bridges.capabilities.retrieve('bridgeID');\n\nconsole.log(capability);", }, python: { - method: 'info.retrieve', + method: 'matrix.bridges.capabilities.retrieve', example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\ninfo = client.info.retrieve()\nprint(info.app)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\ncapability = client.matrix.bridges.capabilities.retrieve(\n "bridgeID",\n)\nprint(capability)', }, go: { - method: 'client.Info.Get', + method: 'client.Matrix.Bridges.Capabilities.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tinfo, err := client.Info.Get(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", info.App)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tcapability, err := client.Matrix.Bridges.Capabilities.Get(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", capability)\n}\n', }, cli: { - method: 'info retrieve', - example: "beeper-desktop-cli info retrieve \\\n --access-token 'My Access Token'", + method: 'capabilities retrieve', + example: + "beeper-desktop-cli matrix:bridges:capabilities retrieve \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", }, php: { - method: 'info->retrieve', + method: 'matrix->bridges->capabilities->retrieve', example: - "info->retrieve();\n\nvar_dump($info);", + "matrix->bridges->capabilities->retrieve('bridgeID');\n\nvar_dump($capability);", }, http: { example: - 'curl http://localhost:23373/v1/info \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/capabilities \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, @@ -3382,7 +3382,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'cli', content: - "# Beeper Desktop CLI\n\nThe official CLI for the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/).\n\n\n\n## Installation\n\n### Installing with Homebrew\n\n~~~sh\nbrew install beeper/tap/beeper-desktop-cli\n~~~\n\n### Installing with Go\n\nTo test or install the CLI locally, you need [Go](https://go.dev/doc/install) version 1.22 or later installed.\n\n~~~sh\ngo install 'github.com/beeper/desktop-api-cli/cmd/beeper-desktop-cli@latest'\n~~~\n\nOnce you have run `go install`, the binary is placed in your Go bin directory:\n\n- **Default location**: `$HOME/go/bin` (or `$GOPATH/bin` if GOPATH is set)\n- **Check your path**: Run `go env GOPATH` to see the base directory\n\nIf commands aren't found after installation, add the Go bin directory to your PATH:\n\n~~~sh\n# Add to your shell profile (.zshrc, .bashrc, etc.)\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n~~~\n\n\n\n### Running Locally\n\nAfter cloning the git repository for this project, you can use the\n`scripts/run` script to run the tool locally:\n\n~~~sh\n./scripts/run args...\n~~~\n\n## Usage\n\nThe CLI follows a resource-based command structure:\n\n~~~sh\nbeeper-desktop-cli [resource] [flags...]\n~~~\n\n~~~sh\nbeeper-desktop-cli chats search \\\n --access-token 'My Access Token' \\\n --account-id matrix \\\n --account-id discordgo \\\n --account-id local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --include-muted \\\n --limit 3 \\\n --type single\n~~~\n\nFor details about specific commands, use the `--help` flag.\n\n### Environment variables\n\n| Environment variable | Description | Required | Default value |\n| --------------------- | --------------------------------------------------------------------------------------------------------------- | -------- | ------------- |\n| `BEEPER_ACCESS_TOKEN` | Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. | no | `null` |\n\n### Global flags\n\n- `--access-token` - Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. (can also be set with `BEEPER_ACCESS_TOKEN` env var)\n- `--help` - Show command line usage\n- `--debug` - Enable debug logging (includes HTTP request/response details)\n- `--version`, `-v` - Show the CLI version\n- `--base-url` - Use a custom API backend URL\n- `--format` - Change the output format (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--format-error` - Change the output format for errors (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--transform` - Transform the data output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n- `--transform-error` - Transform the error output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n\n### Passing files as arguments\n\nTo pass files to your API, you can use the `@myfile.ext` syntax:\n\n~~~bash\nbeeper-desktop-cli --arg @abe.jpg\n~~~\n\nFiles can also be passed inside JSON or YAML blobs:\n\n~~~bash\nbeeper-desktop-cli --arg '{image: \"@abe.jpg\"}'\n# Equivalent:\nbeeper-desktop-cli < --username '\\@abe'\n~~~\n\n#### Explicit encoding\n\nFor JSON endpoints, the CLI tool does filetype sniffing to determine whether the\nfile contents should be sent as a string literal (for plain text files) or as a\nbase64-encoded string literal (for binary files). If you need to explicitly send\nthe file as either plain text or base64-encoded data, you can use\n`@file://myfile.txt` (for string encoding) or `@data://myfile.dat` (for\nbase64-encoding). Note that absolute paths will begin with `@file://` or\n`@data://`, followed by a third `/` (for example, `@file:///tmp/file.txt`).\n\n~~~bash\nbeeper-desktop-cli --arg @data://file.txt\n~~~\n\n## Linking different Go SDK versions\n\nYou can link the CLI against a different version of the Beeper Desktop Go SDK\nfor development purposes using the `./scripts/link` script.\n\nTo link to a specific version from a repository (version can be a branch,\ngit tag, or commit hash):\n\n~~~bash\n./scripts/link github.com/org/repo@version\n~~~\n\nTo link to a local copy of the SDK:\n\n~~~bash\n./scripts/link ../path/to/beeperdesktopapi-go\n~~~\n\nIf you run the link script without any arguments, it will default to `../beeperdesktopapi-go`.\n", + "# Beeper Desktop CLI\n\nThe official CLI for the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/).\n\n\n\n## Installation\n\n### Installing with Homebrew\n\n~~~sh\nbrew install beeper/tap/beeper-desktop-cli\n~~~\n\n### Installing with Go\n\nTo test or install the CLI locally, you need [Go](https://go.dev/doc/install) version 1.22 or later installed.\n\n~~~sh\ngo install 'github.com/beeper/desktop-api-cli/cmd/beeper-desktop-cli@latest'\n~~~\n\nOnce you have run `go install`, the binary is placed in your Go bin directory:\n\n- **Default location**: `$HOME/go/bin` (or `$GOPATH/bin` if GOPATH is set)\n- **Check your path**: Run `go env GOPATH` to see the base directory\n\nIf commands aren't found after installation, add the Go bin directory to your PATH:\n\n~~~sh\n# Add to your shell profile (.zshrc, .bashrc, etc.)\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n~~~\n\n\n\n### Running Locally\n\nAfter cloning the git repository for this project, you can use the\n`scripts/run` script to run the tool locally:\n\n~~~sh\n./scripts/run args...\n~~~\n\n## Usage\n\nThe CLI follows a resource-based command structure:\n\n~~~sh\nbeeper-desktop-cli [resource] [flags...]\n~~~\n\n~~~sh\nbeeper-desktop-cli chats search \\\n --access-token 'My Access Token' \\\n --account-id matrix \\\n --account-id discordgo \\\n --account-id local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --include-muted \\\n --limit 3 \\\n --type single\n~~~\n\nFor details about specific commands, use the `--help` flag.\n\n### Environment variables\n\n| Environment variable | Description | Required |\n| --------------------- | --------------------------------------------------------------------------------------------------------------- | -------- |\n| `BEEPER_ACCESS_TOKEN` | Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. | yes |\n\n### Global flags\n\n- `--access-token` - Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. (can also be set with `BEEPER_ACCESS_TOKEN` env var)\n- `--help` - Show command line usage\n- `--debug` - Enable debug logging (includes HTTP request/response details)\n- `--version`, `-v` - Show the CLI version\n- `--base-url` - Use a custom API backend URL\n- `--format` - Change the output format (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--format-error` - Change the output format for errors (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--transform` - Transform the data output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n- `--transform-error` - Transform the error output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n\n### Passing files as arguments\n\nTo pass files to your API, you can use the `@myfile.ext` syntax:\n\n~~~bash\nbeeper-desktop-cli --arg @abe.jpg\n~~~\n\nFiles can also be passed inside JSON or YAML blobs:\n\n~~~bash\nbeeper-desktop-cli --arg '{image: \"@abe.jpg\"}'\n# Equivalent:\nbeeper-desktop-cli < --username '\\@abe'\n~~~\n\n#### Explicit encoding\n\nFor JSON endpoints, the CLI tool does filetype sniffing to determine whether the\nfile contents should be sent as a string literal (for plain text files) or as a\nbase64-encoded string literal (for binary files). If you need to explicitly send\nthe file as either plain text or base64-encoded data, you can use\n`@file://myfile.txt` (for string encoding) or `@data://myfile.dat` (for\nbase64-encoding). Note that absolute paths will begin with `@file://` or\n`@data://`, followed by a third `/` (for example, `@file:///tmp/file.txt`).\n\n~~~bash\nbeeper-desktop-cli --arg @data://file.txt\n~~~\n\n## Linking different Go SDK versions\n\nYou can link the CLI against a different version of the Beeper Desktop Go SDK\nfor development purposes using the `./scripts/link` script.\n\nTo link to a specific version from a repository (version can be a branch,\ngit tag, or commit hash):\n\n~~~bash\n./scripts/link github.com/org/repo@version\n~~~\n\nTo link to a local copy of the SDK:\n\n~~~bash\n./scripts/link ../path/to/beeperdesktopapi-go\n~~~\n\nIf you run the link script without any arguments, it will default to `../beeperdesktopapi-go`.\n", }, { language: 'go', @@ -3397,7 +3397,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'python', content: - '# Beeper Desktop Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beeper_desktop_api.svg?label=pypi%20(stable))](https://pypi.org/project/beeper_desktop_api/)\n\nThe Beeper Desktop Python library provides convenient access to the Beeper Desktop REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\n\n\n## MCP Server\n\nUse the Beeper Desktop MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40beeper%2Fdesktop-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBiZWVwZXIvZGVza3RvcC1tY3AiXSwiZW52Ijp7IkJFRVBFUl9BQ0NFU1NfVE9LRU4iOiJNeSBBY2Nlc3MgVG9rZW4ifX0)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40beeper%2Fdesktop-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40beeper%2Fdesktop-mcp%22%5D%2C%22env%22%3A%7B%22BEEPER_ACCESS_TOKEN%22%3A%22My%20Access%20Token%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nThe REST API documentation can be found on [developers.beeper.com](https://developers.beeper.com/desktop-api/). The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from the production repo\npip install git+ssh://git@github.com/beeper/desktop-api-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beeper_desktop_api`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\n\npage = client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n)\nprint(page.items)\n```\n\nWhile you can provide a `access_token` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEEPER_ACCESS_TOKEN="My Access Token"` to your `.env` file\nso that your Access Token is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeeperDesktop` instead of `BeeperDesktop` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nclient = AsyncBeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\n\nasync def main() -> None:\n page = await client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n )\n print(page.items)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from the production repo\npip install \'beeper_desktop_api[aiohttp] @ git+ssh://git@github.com/beeper/desktop-api-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beeper_desktop_api import DefaultAioHttpClient\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nasync def main() -> None:\n async with AsyncBeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n page = await client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n )\n print(page.items)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n## Pagination\n\nList methods in the Beeper Desktop API are paginated.\n\nThis library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nall_messages = []\n# Automatically fetches more pages as needed.\nfor message in client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n):\n # Do something with message here\n all_messages.append(message)\nprint(all_messages)\n```\n\nOr, asynchronously:\n\n```python\nimport asyncio\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nclient = AsyncBeeperDesktop()\n\nasync def main() -> None:\n all_messages = []\n # Iterate through items across all pages, issuing requests as needed.\n async for message in client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n):\n all_messages.append(message)\n print(all_messages)\n\nasyncio.run(main())\n```\n\nAlternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:\n\n```python\nfirst_page = await client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n)\nif first_page.has_next_page():\n print(f"will fetch next page using these details: {first_page.next_page_info()}")\n next_page = await first_page.get_next_page()\n print(f"number of items we just fetched: {len(next_page.items)}")\n\n# Remove `await` for non-async usage.\n```\n\nOr just work directly with the returned data:\n\n```python\nfirst_page = await client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n)\n\nprint(f"next page cursor: {first_page.oldest_cursor}") # => "next page cursor: ..."\nfor message in first_page.items:\n print(message.id)\n\n# Remove `await` for non-async usage.\n```\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nresponse = client.matrix.rooms.join(\n room_id_or_alias="!monkeys:matrix.org",\n third_party_signed={\n "token": "random8nonce",\n "mxid": "bob",\n "sender": "alice",\n "signatures": {\n "example.org": {\n "ed25519:0": "some9signature"\n }\n },\n },\n)\nprint(response.third_party_signed)\n```\n\n## File uploads\n\nRequest parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.\n\n```python\nfrom pathlib import Path\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nclient.assets.upload(\n file=Path("/path/to/file"),\n)\n```\n\nThe async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically.\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beeper_desktop_api.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beeper_desktop_api.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beeper_desktop_api.APIError`.\n\n```python\nimport beeper_desktop_api\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\ntry:\n client.accounts.list()\nexcept beeper_desktop_api.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beeper_desktop_api.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beeper_desktop_api.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\n# Configure the default for all requests:\nclient = BeeperDesktop(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).accounts.list()\n```\n\n### Timeouts\n\nBy default requests time out after 30 seconds. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\n# Configure the default for all requests:\nclient = BeeperDesktop(\n # 20 seconds (default is 30 seconds)\n timeout=20.0,\n)\n\n# More granular control:\nclient = BeeperDesktop(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).accounts.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEEPER_LOG` to `info`.\n\n```shell\n$ export BEEPER_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.accounts.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\naccount = response.parse() # get the object that `accounts.list()` would have returned\nprint(account)\n```\n\nThese methods return an [`APIResponse`](https://github.com/beeper/desktop-api-python/tree/main/src/beeper_desktop_api/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/beeper/desktop-api-python/tree/main/src/beeper_desktop_api/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.accounts.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beeper_desktop_api import BeeperDesktop, DefaultHttpxClient\n\nclient = BeeperDesktop(\n # Or use the `BEEPER_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beeper_desktop_api import BeeperDesktop\n\nwith BeeperDesktop() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/beeper/desktop-api-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beeper_desktop_api\nprint(beeper_desktop_api.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', + '# Beeper Desktop Python API library\n\n\n[![PyPI version](https://img.shields.io/pypi/v/beeper_desktop_api.svg?label=pypi%20(stable))](https://pypi.org/project/beeper_desktop_api/)\n\nThe Beeper Desktop Python library provides convenient access to the Beeper Desktop REST API from any Python 3.9+\napplication. The library includes type definitions for all request params and response fields,\nand offers both synchronous and asynchronous clients powered by [httpx](https://github.com/encode/httpx).\n\n\n\n\n\n## MCP Server\n\nUse the Beeper Desktop MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.\n\n[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40beeper%2Fdesktop-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBiZWVwZXIvZGVza3RvcC1tY3AiXSwiZW52Ijp7IkJFRVBFUl9BQ0NFU1NfVE9LRU4iOiJNeSBBY2Nlc3MgVG9rZW4ifX0)\n[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40beeper%2Fdesktop-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40beeper%2Fdesktop-mcp%22%5D%2C%22env%22%3A%7B%22BEEPER_ACCESS_TOKEN%22%3A%22My%20Access%20Token%22%7D%7D)\n\n> Note: You may need to set environment variables in your MCP client.\n\n## Documentation\n\nThe REST API documentation can be found on [developers.beeper.com](https://developers.beeper.com/desktop-api/). The full API of this library can be found in [api.md](api.md).\n\n## Installation\n\n```sh\n# install from the production repo\npip install git+ssh://git@github.com/beeper/desktop-api-python.git\n```\n> [!NOTE]\n> Once this package is [published to PyPI](https://www.stainless.com/docs/guides/publish), this will become: `pip install beeper_desktop_api`\n\n## Usage\n\nThe full API of this library can be found in [api.md](api.md).\n\n```python\nimport os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\n\npage = client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n)\nprint(page.items)\n```\n\nWhile you can provide a `access_token` keyword argument,\nwe recommend using [python-dotenv](https://pypi.org/project/python-dotenv/)\nto add `BEEPER_ACCESS_TOKEN="My Access Token"` to your `.env` file\nso that your Access Token is not stored in source control.\n\n## Async usage\n\nSimply import `AsyncBeeperDesktop` instead of `BeeperDesktop` and use `await` with each API call:\n\n```python\nimport os\nimport asyncio\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nclient = AsyncBeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\n\nasync def main() -> None:\n page = await client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n )\n print(page.items)\n\nasyncio.run(main())\n```\n\nFunctionality between the synchronous and asynchronous clients is otherwise identical.\n\n### With aiohttp\n\nBy default, the async client uses `httpx` for HTTP requests. However, for improved concurrency performance you may also use `aiohttp` as the HTTP backend.\n\nYou can enable this by installing `aiohttp`:\n\n```sh\n# install from the production repo\npip install \'beeper_desktop_api[aiohttp] @ git+ssh://git@github.com/beeper/desktop-api-python.git\'\n```\n\nThen you can enable it by instantiating the client with `http_client=DefaultAioHttpClient()`:\n\n```python\nimport os\nimport asyncio\nfrom beeper_desktop_api import DefaultAioHttpClient\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nasync def main() -> None:\n async with AsyncBeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n http_client=DefaultAioHttpClient(),\n) as client:\n page = await client.chats.search(\n account_ids=["matrix", "discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n include_muted=True,\n limit=3,\n type="single",\n )\n print(page.items)\n\nasyncio.run(main())\n```\n\n\n\n## Using types\n\nNested request parameters are [TypedDicts](https://docs.python.org/3/library/typing.html#typing.TypedDict). Responses are [Pydantic models](https://docs.pydantic.dev) which also provide helper methods for things like:\n\n- Serializing back into JSON, `model.to_json()`\n- Converting to a dictionary, `model.to_dict()`\n\nTyped requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`.\n\n## Pagination\n\nList methods in the Beeper Desktop API are paginated.\n\nThis library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nall_messages = []\n# Automatically fetches more pages as needed.\nfor message in client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n):\n # Do something with message here\n all_messages.append(message)\nprint(all_messages)\n```\n\nOr, asynchronously:\n\n```python\nimport asyncio\nfrom beeper_desktop_api import AsyncBeeperDesktop\n\nclient = AsyncBeeperDesktop()\n\nasync def main() -> None:\n all_messages = []\n # Iterate through items across all pages, issuing requests as needed.\n async for message in client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n):\n all_messages.append(message)\n print(all_messages)\n\nasyncio.run(main())\n```\n\nAlternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages:\n\n```python\nfirst_page = await client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n)\nif first_page.has_next_page():\n print(f"will fetch next page using these details: {first_page.next_page_info()}")\n next_page = await first_page.get_next_page()\n print(f"number of items we just fetched: {len(next_page.items)}")\n\n# Remove `await` for non-async usage.\n```\n\nOr just work directly with the returned data:\n\n```python\nfirst_page = await client.messages.search(\n account_ids=["discordgo", "local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc"],\n limit=10,\n query="oauth",\n)\n\nprint(f"next page cursor: {first_page.oldest_cursor}") # => "next page cursor: ..."\nfor message in first_page.items:\n print(message.id)\n\n# Remove `await` for non-async usage.\n```\n\n## Nested params\n\nNested parameters are dictionaries, typed using `TypedDict`, for example:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nchat = client.chats.update(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n draft={\n "text": "text"\n },\n)\nprint(chat.draft)\n```\n\n## File uploads\n\nRequest parameters that correspond to file uploads can be passed as `bytes`, or a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance or a tuple of `(filename, contents, media type)`.\n\n```python\nfrom pathlib import Path\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\nclient.assets.upload(\n file=Path("/path/to/file"),\n)\n```\n\nThe async client uses the exact same interface. If you pass a [`PathLike`](https://docs.python.org/3/library/os.html#os.PathLike) instance, the file contents will be read asynchronously automatically.\n\n## Handling errors\n\nWhen the library is unable to connect to the API (for example, due to network connection problems or a timeout), a subclass of `beeper_desktop_api.APIConnectionError` is raised.\n\nWhen the API returns a non-success status code (that is, 4xx or 5xx\nresponse), a subclass of `beeper_desktop_api.APIStatusError` is raised, containing `status_code` and `response` properties.\n\nAll errors inherit from `beeper_desktop_api.APIError`.\n\n```python\nimport beeper_desktop_api\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\n\ntry:\n client.accounts.list()\nexcept beeper_desktop_api.APIConnectionError as e:\n print("The server could not be reached")\n print(e.__cause__) # an underlying Exception, likely raised within httpx.\nexcept beeper_desktop_api.RateLimitError as e:\n print("A 429 status code was received; we should back off a bit.")\nexcept beeper_desktop_api.APIStatusError as e:\n print("Another non-200-range status code was received")\n print(e.status_code)\n print(e.response)\n```\n\nError codes are as follows:\n\n| Status Code | Error Type |\n| ----------- | -------------------------- |\n| 400 | `BadRequestError` |\n| 401 | `AuthenticationError` |\n| 403 | `PermissionDeniedError` |\n| 404 | `NotFoundError` |\n| 422 | `UnprocessableEntityError` |\n| 429 | `RateLimitError` |\n| >=500 | `InternalServerError` |\n| N/A | `APIConnectionError` |\n\n### Retries\n\nCertain errors are automatically retried 2 times by default, with a short exponential backoff.\nConnection errors (for example, due to a network connectivity problem), 408 Request Timeout, 409 Conflict,\n429 Rate Limit, and >=500 Internal errors are all retried by default.\n\nYou can use the `max_retries` option to configure or disable retry settings:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\n# Configure the default for all requests:\nclient = BeeperDesktop(\n # default is 2\n max_retries=0,\n)\n\n# Or, configure per-request:\nclient.with_options(max_retries = 5).accounts.list()\n```\n\n### Timeouts\n\nBy default requests time out after 30 seconds. You can configure this with a `timeout` option,\nwhich accepts a float or an [`httpx.Timeout`](https://www.python-httpx.org/advanced/timeouts/#fine-tuning-the-configuration) object:\n\n```python\nfrom beeper_desktop_api import BeeperDesktop\n\n# Configure the default for all requests:\nclient = BeeperDesktop(\n # 20 seconds (default is 30 seconds)\n timeout=20.0,\n)\n\n# More granular control:\nclient = BeeperDesktop(\n timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),\n)\n\n# Override per-request:\nclient.with_options(timeout = 5.0).accounts.list()\n```\n\nOn timeout, an `APITimeoutError` is thrown.\n\nNote that requests that time out are [retried twice by default](#retries).\n\n\n\n## Advanced\n\n### Logging\n\nWe use the standard library [`logging`](https://docs.python.org/3/library/logging.html) module.\n\nYou can enable logging by setting the environment variable `BEEPER_LOG` to `info`.\n\n```shell\n$ export BEEPER_LOG=info\n```\n\nOr to `debug` for more verbose logging.\n\n### How to tell whether `None` means `null` or missing\n\nIn an API response, a field may be explicitly `null`, or missing entirely; in either case, its value is `None` in this library. You can differentiate the two cases with `.model_fields_set`:\n\n```py\nif response.my_field is None:\n if \'my_field\' not in response.model_fields_set:\n print(\'Got json like {}, without a "my_field" key present at all.\')\n else:\n print(\'Got json like {"my_field": null}.\')\n```\n\n### Accessing raw response data (e.g. headers)\n\nThe "raw" Response object can be accessed by prefixing `.with_raw_response.` to any HTTP method call, e.g.,\n\n```py\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.accounts.with_raw_response.list()\nprint(response.headers.get(\'X-My-Header\'))\n\naccount = response.parse() # get the object that `accounts.list()` would have returned\nprint(account)\n```\n\nThese methods return an [`APIResponse`](https://github.com/beeper/desktop-api-python/tree/main/src/beeper_desktop_api/_response.py) object.\n\nThe async client returns an [`AsyncAPIResponse`](https://github.com/beeper/desktop-api-python/tree/main/src/beeper_desktop_api/_response.py) with the same structure, the only difference being `await`able methods for reading the response content.\n\n#### `.with_streaming_response`\n\nThe above interface eagerly reads the full response body when you make the request, which may not always be what you want.\n\nTo stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods.\n\n```python\nwith client.accounts.with_streaming_response.list() as response :\n print(response.headers.get(\'X-My-Header\'))\n\n for line in response.iter_lines():\n print(line)\n```\n\nThe context manager is required so that the response will reliably be closed.\n\n### Making custom/undocumented requests\n\nThis library is typed for convenient access to the documented API.\n\nIf you need to access undocumented endpoints, params, or response properties, the library can still be used.\n\n#### Undocumented endpoints\n\nTo make requests to undocumented endpoints, you can make requests using `client.get`, `client.post`, and other\nhttp verbs. Options on the client will be respected (such as retries) when making this request.\n\n```py\nimport httpx\n\nresponse = client.post(\n "/foo",\n cast_to=httpx.Response,\n body={"my_param": True},\n)\n\nprint(response.headers.get("x-foo"))\n```\n\n#### Undocumented request params\n\nIf you want to explicitly send an extra param, you can do so with the `extra_query`, `extra_body`, and `extra_headers` request\noptions.\n\n#### Undocumented response properties\n\nTo access undocumented response properties, you can access the extra fields like `response.unknown_prop`. You\ncan also get all the extra fields on the Pydantic model as a dict with\n[`response.model_extra`](https://docs.pydantic.dev/latest/api/base_model/#pydantic.BaseModel.model_extra).\n\n### Configuring the HTTP client\n\nYou can directly override the [httpx client](https://www.python-httpx.org/api/#client) to customize it for your use case, including:\n\n- Support for [proxies](https://www.python-httpx.org/advanced/proxies/)\n- Custom [transports](https://www.python-httpx.org/advanced/transports/)\n- Additional [advanced](https://www.python-httpx.org/advanced/clients/) functionality\n\n```python\nimport httpx\nfrom beeper_desktop_api import BeeperDesktop, DefaultHttpxClient\n\nclient = BeeperDesktop(\n # Or use the `BEEPER_BASE_URL` env var\n base_url="http://my.test.server.example.com:8083",\n http_client=DefaultHttpxClient(proxy="http://my.test.proxy.example.com", transport=httpx.HTTPTransport(local_address="0.0.0.0")),\n)\n```\n\nYou can also customize the client on a per-request basis by using `with_options()`:\n\n```python\nclient.with_options(http_client=DefaultHttpxClient(...))\n```\n\n### Managing HTTP resources\n\nBy default the library closes underlying HTTP connections whenever the client is [garbage collected](https://docs.python.org/3/reference/datamodel.html#object.__del__). You can manually close the client using the `.close()` method if desired, or with a context manager that closes when exiting.\n\n```py\nfrom beeper_desktop_api import BeeperDesktop\n\nwith BeeperDesktop() as client:\n # make requests here\n ...\n\n# HTTP client is now closed\n```\n\n## Versioning\n\nThis package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions:\n\n1. Changes that only affect static types, without breaking runtime behavior.\n2. Changes to library internals which are technically public but not intended or documented for external use. _(Please open a GitHub issue to let us know if you are relying on such internals.)_\n3. Changes that we do not expect to impact the vast majority of users in practice.\n\nWe take backwards-compatibility seriously and work hard to ensure you can rely on a smooth upgrade experience.\n\nWe are keen for your feedback; please open an [issue](https://www.github.com/beeper/desktop-api-python/issues) with questions, bugs, or suggestions.\n\n### Determining the installed version\n\nIf you\'ve upgraded to the latest version but aren\'t seeing any new features you were expecting then your python environment is likely still using an older version.\n\nYou can determine the version that is being used at runtime with:\n\n```py\nimport beeper_desktop_api\nprint(beeper_desktop_api.__version__)\n```\n\n## Requirements\n\nPython 3.9 or higher.\n\n## Contributing\n\nSee [the contributing documentation](./CONTRIBUTING.md).\n', }, { language: 'typescript', diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts index 3cf2a1f2..5b10e8f0 100644 --- a/packages/mcp-server/src/methods.ts +++ b/packages/mcp-server/src/methods.ts @@ -22,6 +22,180 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/v1/search', }, + { + clientCallName: 'client.accounts.list', + fullyQualifiedName: 'accounts.list', + httpMethod: 'get', + httpPath: '/v1/accounts', + }, + { + clientCallName: 'client.accounts.contacts.list', + fullyQualifiedName: 'accounts.contacts.list', + httpMethod: 'get', + httpPath: '/v1/accounts/{accountID}/contacts/list', + }, + { + clientCallName: 'client.accounts.contacts.search', + fullyQualifiedName: 'accounts.contacts.search', + httpMethod: 'get', + httpPath: '/v1/accounts/{accountID}/contacts', + }, + { + clientCallName: 'client.bridges.list', + fullyQualifiedName: 'bridges.list', + httpMethod: 'get', + httpPath: '/v1/bridges', + }, + { + clientCallName: 'client.chats.create', + fullyQualifiedName: 'chats.create', + httpMethod: 'post', + httpPath: '/v1/chats', + }, + { + clientCallName: 'client.chats.retrieve', + fullyQualifiedName: 'chats.retrieve', + httpMethod: 'get', + httpPath: '/v1/chats/{chatID}', + }, + { + clientCallName: 'client.chats.update', + fullyQualifiedName: 'chats.update', + httpMethod: 'patch', + httpPath: '/v1/chats/{chatID}', + }, + { + clientCallName: 'client.chats.list', + fullyQualifiedName: 'chats.list', + httpMethod: 'get', + httpPath: '/v1/chats', + }, + { + clientCallName: 'client.chats.archive', + fullyQualifiedName: 'chats.archive', + httpMethod: 'post', + httpPath: '/v1/chats/{chatID}/archive', + }, + { + clientCallName: 'client.chats.markRead', + fullyQualifiedName: 'chats.markRead', + httpMethod: 'post', + httpPath: '/v1/chats/{chatID}/read', + }, + { + clientCallName: 'client.chats.markUnread', + fullyQualifiedName: 'chats.markUnread', + httpMethod: 'post', + httpPath: '/v1/chats/{chatID}/unread', + }, + { + clientCallName: 'client.chats.notifyAnyway', + fullyQualifiedName: 'chats.notifyAnyway', + httpMethod: 'post', + httpPath: '/v1/chats/{chatID}/notify-anyway', + }, + { + clientCallName: 'client.chats.search', + fullyQualifiedName: 'chats.search', + httpMethod: 'get', + httpPath: '/v1/chats/search', + }, + { + clientCallName: 'client.chats.start', + fullyQualifiedName: 'chats.start', + httpMethod: 'post', + httpPath: '/v1/chats/start', + }, + { + clientCallName: 'client.chats.reminders.create', + fullyQualifiedName: 'chats.reminders.create', + httpMethod: 'post', + httpPath: '/v1/chats/{chatID}/reminders', + }, + { + clientCallName: 'client.chats.reminders.delete', + fullyQualifiedName: 'chats.reminders.delete', + httpMethod: 'delete', + httpPath: '/v1/chats/{chatID}/reminders', + }, + { + clientCallName: 'client.chats.messages.reactions.delete', + fullyQualifiedName: 'chats.messages.reactions.delete', + httpMethod: 'delete', + httpPath: '/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}', + }, + { + clientCallName: 'client.chats.messages.reactions.add', + fullyQualifiedName: 'chats.messages.reactions.add', + httpMethod: 'post', + httpPath: '/v1/chats/{chatID}/messages/{messageID}/reactions', + }, + { + clientCallName: 'client.messages.retrieve', + fullyQualifiedName: 'messages.retrieve', + httpMethod: 'get', + httpPath: '/v1/chats/{chatID}/messages/{messageID}', + }, + { + clientCallName: 'client.messages.update', + fullyQualifiedName: 'messages.update', + httpMethod: 'put', + httpPath: '/v1/chats/{chatID}/messages/{messageID}', + }, + { + clientCallName: 'client.messages.list', + fullyQualifiedName: 'messages.list', + httpMethod: 'get', + httpPath: '/v1/chats/{chatID}/messages', + }, + { + clientCallName: 'client.messages.delete', + fullyQualifiedName: 'messages.delete', + httpMethod: 'delete', + httpPath: '/v1/chats/{chatID}/messages/{messageID}', + }, + { + clientCallName: 'client.messages.search', + fullyQualifiedName: 'messages.search', + httpMethod: 'get', + httpPath: '/v1/messages/search', + }, + { + clientCallName: 'client.messages.send', + fullyQualifiedName: 'messages.send', + httpMethod: 'post', + httpPath: '/v1/chats/{chatID}/messages', + }, + { + clientCallName: 'client.assets.download', + fullyQualifiedName: 'assets.download', + httpMethod: 'post', + httpPath: '/v1/assets/download', + }, + { + clientCallName: 'client.assets.serve', + fullyQualifiedName: 'assets.serve', + httpMethod: 'get', + httpPath: '/v1/assets/serve', + }, + { + clientCallName: 'client.assets.upload', + fullyQualifiedName: 'assets.upload', + httpMethod: 'post', + httpPath: '/v1/assets/upload', + }, + { + clientCallName: 'client.assets.uploadBase64', + fullyQualifiedName: 'assets.uploadBase64', + httpMethod: 'post', + httpPath: '/v1/assets/upload/base64', + }, + { + clientCallName: 'client.info.retrieve', + fullyQualifiedName: 'info.retrieve', + httpMethod: 'get', + httpPath: '/v1/info', + }, { clientCallName: 'client.app.status', fullyQualifiedName: 'app.status', @@ -118,30 +292,6 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'post', httpPath: '/v1/app/e2ee/verification/{verificationID}/sas/start', }, - { - clientCallName: 'client.accounts.list', - fullyQualifiedName: 'accounts.list', - httpMethod: 'get', - httpPath: '/v1/accounts', - }, - { - clientCallName: 'client.accounts.contacts.list', - fullyQualifiedName: 'accounts.contacts.list', - httpMethod: 'get', - httpPath: '/v1/accounts/{accountID}/contacts/list', - }, - { - clientCallName: 'client.accounts.contacts.search', - fullyQualifiedName: 'accounts.contacts.search', - httpMethod: 'get', - httpPath: '/v1/accounts/{accountID}/contacts', - }, - { - clientCallName: 'client.bridges.list', - fullyQualifiedName: 'bridges.list', - httpMethod: 'get', - httpPath: '/v1/bridges', - }, { clientCallName: 'client.matrix.users.retrieveProfile', fullyQualifiedName: 'matrix.users.retrieveProfile', @@ -299,156 +449,6 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities', }, - { - clientCallName: 'client.chats.create', - fullyQualifiedName: 'chats.create', - httpMethod: 'post', - httpPath: '/v1/chats', - }, - { - clientCallName: 'client.chats.retrieve', - fullyQualifiedName: 'chats.retrieve', - httpMethod: 'get', - httpPath: '/v1/chats/{chatID}', - }, - { - clientCallName: 'client.chats.update', - fullyQualifiedName: 'chats.update', - httpMethod: 'patch', - httpPath: '/v1/chats/{chatID}', - }, - { - clientCallName: 'client.chats.list', - fullyQualifiedName: 'chats.list', - httpMethod: 'get', - httpPath: '/v1/chats', - }, - { - clientCallName: 'client.chats.archive', - fullyQualifiedName: 'chats.archive', - httpMethod: 'post', - httpPath: '/v1/chats/{chatID}/archive', - }, - { - clientCallName: 'client.chats.markRead', - fullyQualifiedName: 'chats.markRead', - httpMethod: 'post', - httpPath: '/v1/chats/{chatID}/read', - }, - { - clientCallName: 'client.chats.markUnread', - fullyQualifiedName: 'chats.markUnread', - httpMethod: 'post', - httpPath: '/v1/chats/{chatID}/unread', - }, - { - clientCallName: 'client.chats.notifyAnyway', - fullyQualifiedName: 'chats.notifyAnyway', - httpMethod: 'post', - httpPath: '/v1/chats/{chatID}/notify-anyway', - }, - { - clientCallName: 'client.chats.search', - fullyQualifiedName: 'chats.search', - httpMethod: 'get', - httpPath: '/v1/chats/search', - }, - { - clientCallName: 'client.chats.start', - fullyQualifiedName: 'chats.start', - httpMethod: 'post', - httpPath: '/v1/chats/start', - }, - { - clientCallName: 'client.chats.reminders.create', - fullyQualifiedName: 'chats.reminders.create', - httpMethod: 'post', - httpPath: '/v1/chats/{chatID}/reminders', - }, - { - clientCallName: 'client.chats.reminders.delete', - fullyQualifiedName: 'chats.reminders.delete', - httpMethod: 'delete', - httpPath: '/v1/chats/{chatID}/reminders', - }, - { - clientCallName: 'client.chats.messages.reactions.delete', - fullyQualifiedName: 'chats.messages.reactions.delete', - httpMethod: 'delete', - httpPath: '/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}', - }, - { - clientCallName: 'client.chats.messages.reactions.add', - fullyQualifiedName: 'chats.messages.reactions.add', - httpMethod: 'post', - httpPath: '/v1/chats/{chatID}/messages/{messageID}/reactions', - }, - { - clientCallName: 'client.messages.retrieve', - fullyQualifiedName: 'messages.retrieve', - httpMethod: 'get', - httpPath: '/v1/chats/{chatID}/messages/{messageID}', - }, - { - clientCallName: 'client.messages.update', - fullyQualifiedName: 'messages.update', - httpMethod: 'put', - httpPath: '/v1/chats/{chatID}/messages/{messageID}', - }, - { - clientCallName: 'client.messages.list', - fullyQualifiedName: 'messages.list', - httpMethod: 'get', - httpPath: '/v1/chats/{chatID}/messages', - }, - { - clientCallName: 'client.messages.delete', - fullyQualifiedName: 'messages.delete', - httpMethod: 'delete', - httpPath: '/v1/chats/{chatID}/messages/{messageID}', - }, - { - clientCallName: 'client.messages.search', - fullyQualifiedName: 'messages.search', - httpMethod: 'get', - httpPath: '/v1/messages/search', - }, - { - clientCallName: 'client.messages.send', - fullyQualifiedName: 'messages.send', - httpMethod: 'post', - httpPath: '/v1/chats/{chatID}/messages', - }, - { - clientCallName: 'client.assets.download', - fullyQualifiedName: 'assets.download', - httpMethod: 'post', - httpPath: '/v1/assets/download', - }, - { - clientCallName: 'client.assets.serve', - fullyQualifiedName: 'assets.serve', - httpMethod: 'get', - httpPath: '/v1/assets/serve', - }, - { - clientCallName: 'client.assets.upload', - fullyQualifiedName: 'assets.upload', - httpMethod: 'post', - httpPath: '/v1/assets/upload', - }, - { - clientCallName: 'client.assets.uploadBase64', - fullyQualifiedName: 'assets.uploadBase64', - httpMethod: 'post', - httpPath: '/v1/assets/upload/base64', - }, - { - clientCallName: 'client.info.retrieve', - fullyQualifiedName: 'info.retrieve', - httpMethod: 'get', - httpPath: '/v1/info', - }, ]; function allowedMethodsForCodeTool(options: McpOptions | undefined): SdkMethod[] | undefined { diff --git a/src/client.ts b/src/client.ts index 50880e47..232b4ac7 100644 --- a/src/client.ts +++ b/src/client.ts @@ -98,7 +98,7 @@ export interface ClientOptions { /** * Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. */ - accessToken?: string | null | undefined; + accessToken?: string | undefined; /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" @@ -173,7 +173,7 @@ export interface ClientOptions { * Base class for Beeper Desktop API clients. */ export class BaseBeeperDesktop { - accessToken: string | null; + accessToken: string; baseURL: string; maxRetries: number; @@ -190,7 +190,7 @@ export class BaseBeeperDesktop { /** * API Client for interfacing with the Beeper Desktop API. * - * @param {string | null | undefined} [opts.accessToken=process.env['BEEPER_ACCESS_TOKEN'] ?? null] + * @param {string | undefined} [opts.accessToken=process.env['BEEPER_ACCESS_TOKEN'] ?? undefined] * @param {string} [opts.baseURL=process.env['BEEPER_BASE_URL'] ?? http://localhost:23373] - Override the default base URL for the API. * @param {number} [opts.timeout=30 seconds] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {MergedRequestInit} [opts.fetchOptions] - Additional `RequestInit` options to be passed to `fetch` calls. @@ -201,9 +201,15 @@ export class BaseBeeperDesktop { */ constructor({ baseURL = readEnv('BEEPER_BASE_URL'), - accessToken = readEnv('BEEPER_ACCESS_TOKEN') ?? null, + accessToken = readEnv('BEEPER_ACCESS_TOKEN'), ...opts }: ClientOptions = {}) { + if (accessToken === undefined) { + throw new Errors.BeeperDesktopError( + "The BEEPER_ACCESS_TOKEN environment variable is missing or empty; either provide it, or instantiate the BeeperDesktop client with an accessToken option, like new BeeperDesktop({ accessToken: 'My Access Token' }).", + ); + } + const options: ClientOptions = { accessToken, ...opts, @@ -314,9 +320,6 @@ export class BaseBeeperDesktop { } protected async bearerAuth(opts: FinalRequestOptions): Promise { - if (this.accessToken == null) { - return undefined; - } return buildHeaders([{ Authorization: `Bearer ${this.accessToken}` }]); } @@ -854,10 +857,6 @@ export class BeeperDesktop extends BaseBeeperDesktop { static toFile = Uploads.toFile; - /** - * Manage Beeper app login and encrypted messaging setup - */ - app: API.App = new API.App(this); /** * Manage connected chat accounts */ @@ -866,10 +865,6 @@ export class BeeperDesktop extends BaseBeeperDesktop { * Manage bridge-backed account types and account availability */ bridges: API.Bridges = new API.Bridges(this); - /** - * Matrix-compatible APIs for accounts, rooms, and connected network bridges. - */ - matrix: API.Matrix = new API.Matrix(this); /** * Manage chats */ @@ -886,16 +881,24 @@ export class BeeperDesktop extends BaseBeeperDesktop { * Server discovery and capability metadata. Use /v1/info before authentication setup. */ info: API.Info = new API.Info(this); + /** + * Manage Beeper app login and encrypted messaging setup + */ + app: API.App = new API.App(this); + /** + * Matrix-compatible APIs for accounts, rooms, and connected network bridges. + */ + matrix: API.Matrix = new API.Matrix(this); } -BeeperDesktop.App = App; BeeperDesktop.Accounts = Accounts; BeeperDesktop.Bridges = Bridges; -BeeperDesktop.Matrix = Matrix; BeeperDesktop.Chats = Chats; BeeperDesktop.Messages = Messages; BeeperDesktop.Assets = Assets; BeeperDesktop.Info = Info; +BeeperDesktop.App = App; +BeeperDesktop.Matrix = Matrix; export declare namespace BeeperDesktop { export type RequestOptions = Opts.RequestOptions; @@ -916,17 +919,6 @@ export declare namespace BeeperDesktop { type SearchParams as SearchParams, }; - export { - App as App, - type LoginRegistrationRequiredResponse as LoginRegistrationRequiredResponse, - type LoginResponse as LoginResponse, - type LoginResponseOutput as LoginResponseOutput, - type RecoveryCodeResetResponse as RecoveryCodeResetResponse, - type StartVerificationResponse as StartVerificationResponse, - type StateMutationResponse as StateMutationResponse, - type AppStatusResponse as AppStatusResponse, - }; - export { Accounts as Accounts, type Account as Account, type AccountListResponse as AccountListResponse }; export { @@ -935,8 +927,6 @@ export declare namespace BeeperDesktop { type BridgeListResponse as BridgeListResponse, }; - export { Matrix as Matrix }; - export { Chats as Chats, type Chat as Chat, @@ -982,6 +972,19 @@ export declare namespace BeeperDesktop { export { Info as Info, type InfoRetrieveResponse as InfoRetrieveResponse }; + export { + App as App, + type LoginRegistrationRequiredResponse as LoginRegistrationRequiredResponse, + type LoginResponse as LoginResponse, + type LoginResponseOutput as LoginResponseOutput, + type RecoveryCodeResetResponse as RecoveryCodeResetResponse, + type StartVerificationResponse as StartVerificationResponse, + type StateMutationResponse as StateMutationResponse, + type AppStatusResponse as AppStatusResponse, + }; + + export { Matrix as Matrix }; + export type AppStateSnapshot = API.AppStateSnapshot; export type Attachment = API.Attachment; export type Error = API.Error; diff --git a/src/tree-shakable.ts b/src/tree-shakable.ts index 4df08909..f7b9ba0b 100644 --- a/src/tree-shakable.ts +++ b/src/tree-shakable.ts @@ -18,11 +18,11 @@ type InferClientStructure = * * @example * ```ts - * import { App } from `@beeper/desktop-api/resources/app`; + * import { Accounts } from `@beeper/desktop-api/resources/accounts`; * import { createClient } from `@beeper/desktop-api/tree-shakable`; * * const client = createClient({ - * resources: [App], + * resources: [Accounts], * }); * ``` */ From 0a91186fa1a0811dc9eeb9d43c8093aaeb115e95 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 17 May 2026 13:01:02 +0000 Subject: [PATCH 10/17] feat(api): api update --- .stats.yml | 8 +- README.md | 4 +- api.md | 289 +- packages/mcp-server/src/code-tool-worker.ts | 61 +- packages/mcp-server/src/local-docs-search.ts | 3016 +++++++---------- packages/mcp-server/src/methods.ts | 295 +- src/client.ts | 75 +- src/resources/accounts/accounts.ts | 147 +- src/resources/accounts/index.ts | 9 +- src/resources/app/app.ts | 1129 ++++-- src/resources/app/e2ee/e2ee.ts | 60 - src/resources/app/e2ee/index.ts | 19 - src/resources/app/e2ee/recovery-code.ts | 3 - .../app/e2ee/recovery-code/recovery-code.ts | 550 --- src/resources/app/e2ee/verification/sas.ts | 518 --- .../app/e2ee/verification/verification.ts | 827 ----- src/resources/app/index.ts | 23 +- src/resources/app/login.ts | 765 +---- src/resources/app/login/index.ts | 14 + src/resources/app/login/login.ts | 821 +++++ .../app/{e2ee => login}/verification.ts | 0 src/resources/app/login/verification/index.ts | 9 + .../verification/recovery-key.ts} | 2 +- .../verification/recovery-key}/index.ts | 11 +- .../verification/recovery-key/recovery-key.ts | 327 ++ .../verification/recovery-key}/reset.ts | 240 +- .../app/login/verification/verification.ts | 33 + .../{matrix.ts => app/verifications.ts} | 2 +- .../verification => verifications}/index.ts | 10 +- .../verification => verifications}/qr.ts | 475 ++- src/resources/app/verifications/sas.ts | 807 +++++ .../app/verifications/verifications.ts | 1785 ++++++++++ src/resources/bridges.ts | 106 +- src/resources/bridges/bridges.ts | 510 +++ src/resources/bridges/connections.ts | 102 + src/resources/bridges/index.ts | 36 + src/resources/bridges/login-flows.ts | 36 + .../bridges.ts => bridges/login-sessions.ts} | 2 +- src/resources/bridges/login-sessions/index.ts | 11 + .../bridges/login-sessions/login-sessions.ts | 105 + src/resources/bridges/login-sessions/steps.ts | 73 + src/resources/index.ts | 37 +- src/resources/matrix/bridges/auth.ts | 1950 ----------- src/resources/matrix/bridges/bridges.ts | 125 - src/resources/matrix/bridges/capabilities.ts | 45 - src/resources/matrix/bridges/contacts.ts | 94 - src/resources/matrix/bridges/index.ts | 38 - src/resources/matrix/bridges/rooms.ts | 231 -- src/resources/matrix/bridges/users.ts | 176 - src/resources/matrix/index.ts | 15 - src/resources/matrix/matrix.ts | 61 - src/resources/matrix/rooms.ts | 3 - src/resources/matrix/rooms/account-data.ts | 113 - src/resources/matrix/rooms/events.ts | 148 - src/resources/matrix/rooms/index.ts | 28 - src/resources/matrix/rooms/rooms.ts | 435 --- src/resources/matrix/rooms/state.ts | 194 -- src/resources/matrix/users.ts | 3 - src/resources/matrix/users/account-data.ts | 95 - src/resources/matrix/users/index.ts | 11 - src/resources/matrix/users/users.ts | 71 - src/resources/shared.ts | 101 +- tests/api-resources/accounts/accounts.test.ts | 11 + tests/api-resources/app/app.test.ts | 4 +- .../e2ee/recovery-code/recovery-code.test.ts | 55 - .../app/{ => login}/login.test.ts | 2 +- .../recovery-key/recovery-key.test.ts} | 24 +- .../verification/recovery-key}/reset.test.ts | 18 +- .../verification => verifications}/qr.test.ts | 14 +- .../sas.test.ts | 14 +- .../app/verifications/verifications.test.ts | 105 + tests/api-resources/bridges.test.ts | 32 - .../rooms.test.ts => bridges/bridges.test.ts} | 30 +- .../api-resources/bridges/connections.test.ts | 80 + .../login-flows.test.ts} | 20 +- .../login-sessions/login-sessions.test.ts} | 51 +- .../bridges/login-sessions/steps.test.ts | 55 + .../api-resources/matrix/bridges/auth.test.ts | 166 - .../matrix/bridges/contacts.test.ts | 51 - .../matrix/bridges/rooms.test.ts | 74 - .../matrix/bridges/users.test.ts | 69 - .../matrix/rooms/account-data.test.ts | 73 - .../api-resources/matrix/rooms/events.test.ts | 48 - .../api-resources/matrix/rooms/state.test.ts | 62 - .../matrix/users/account-data.test.ts | 69 - 85 files changed, 8050 insertions(+), 10366 deletions(-) delete mode 100644 src/resources/app/e2ee/e2ee.ts delete mode 100644 src/resources/app/e2ee/index.ts delete mode 100644 src/resources/app/e2ee/recovery-code.ts delete mode 100644 src/resources/app/e2ee/recovery-code/recovery-code.ts delete mode 100644 src/resources/app/e2ee/verification/sas.ts delete mode 100644 src/resources/app/e2ee/verification/verification.ts create mode 100644 src/resources/app/login/index.ts create mode 100644 src/resources/app/login/login.ts rename src/resources/app/{e2ee => login}/verification.ts (100%) create mode 100644 src/resources/app/login/verification/index.ts rename src/resources/app/{e2ee.ts => login/verification/recovery-key.ts} (69%) rename src/resources/app/{e2ee/recovery-code => login/verification/recovery-key}/index.ts (59%) create mode 100644 src/resources/app/login/verification/recovery-key/recovery-key.ts rename src/resources/app/{e2ee/recovery-code => login/verification/recovery-key}/reset.ts (68%) create mode 100644 src/resources/app/login/verification/verification.ts rename src/resources/{matrix.ts => app/verifications.ts} (69%) rename src/resources/app/{e2ee/verification => verifications}/index.ts (62%) rename src/resources/app/{e2ee/verification => verifications}/qr.ts (50%) create mode 100644 src/resources/app/verifications/sas.ts create mode 100644 src/resources/app/verifications/verifications.ts create mode 100644 src/resources/bridges/bridges.ts create mode 100644 src/resources/bridges/connections.ts create mode 100644 src/resources/bridges/index.ts create mode 100644 src/resources/bridges/login-flows.ts rename src/resources/{matrix/bridges.ts => bridges/login-sessions.ts} (68%) create mode 100644 src/resources/bridges/login-sessions/index.ts create mode 100644 src/resources/bridges/login-sessions/login-sessions.ts create mode 100644 src/resources/bridges/login-sessions/steps.ts delete mode 100644 src/resources/matrix/bridges/auth.ts delete mode 100644 src/resources/matrix/bridges/bridges.ts delete mode 100644 src/resources/matrix/bridges/capabilities.ts delete mode 100644 src/resources/matrix/bridges/contacts.ts delete mode 100644 src/resources/matrix/bridges/index.ts delete mode 100644 src/resources/matrix/bridges/rooms.ts delete mode 100644 src/resources/matrix/bridges/users.ts delete mode 100644 src/resources/matrix/index.ts delete mode 100644 src/resources/matrix/matrix.ts delete mode 100644 src/resources/matrix/rooms.ts delete mode 100644 src/resources/matrix/rooms/account-data.ts delete mode 100644 src/resources/matrix/rooms/events.ts delete mode 100644 src/resources/matrix/rooms/index.ts delete mode 100644 src/resources/matrix/rooms/rooms.ts delete mode 100644 src/resources/matrix/rooms/state.ts delete mode 100644 src/resources/matrix/users.ts delete mode 100644 src/resources/matrix/users/account-data.ts delete mode 100644 src/resources/matrix/users/index.ts delete mode 100644 src/resources/matrix/users/users.ts delete mode 100644 tests/api-resources/app/e2ee/recovery-code/recovery-code.test.ts rename tests/api-resources/app/{ => login}/login.test.ts (99%) rename tests/api-resources/{matrix/bridges/capabilities.test.ts => app/login/verification/recovery-key/recovery-key.test.ts} (53%) rename tests/api-resources/app/{e2ee/recovery-code => login/verification/recovery-key}/reset.test.ts (74%) rename tests/api-resources/app/{e2ee/verification => verifications}/qr.test.ts (76%) rename tests/api-resources/app/{e2ee/verification => verifications}/sas.test.ts (77%) create mode 100644 tests/api-resources/app/verifications/verifications.test.ts delete mode 100644 tests/api-resources/bridges.test.ts rename tests/api-resources/{matrix/rooms/rooms.test.ts => bridges/bridges.test.ts} (63%) create mode 100644 tests/api-resources/bridges/connections.test.ts rename tests/api-resources/{matrix/users/users.test.ts => bridges/login-flows.test.ts} (61%) rename tests/api-resources/{app/e2ee/verification/verification.test.ts => bridges/login-sessions/login-sessions.test.ts} (59%) create mode 100644 tests/api-resources/bridges/login-sessions/steps.test.ts delete mode 100644 tests/api-resources/matrix/bridges/auth.test.ts delete mode 100644 tests/api-resources/matrix/bridges/contacts.test.ts delete mode 100644 tests/api-resources/matrix/bridges/rooms.test.ts delete mode 100644 tests/api-resources/matrix/bridges/users.test.ts delete mode 100644 tests/api-resources/matrix/rooms/account-data.test.ts delete mode 100644 tests/api-resources/matrix/rooms/events.test.ts delete mode 100644 tests/api-resources/matrix/rooms/state.test.ts delete mode 100644 tests/api-resources/matrix/users/account-data.test.ts diff --git a/.stats.yml b/.stats.yml index a6a4fc82..c490046e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 72 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-0427b028ffd00b4f8b75084116f801658d0279117b2d0e522d1f257c998f1fd0.yml -openapi_spec_hash: af3ed0745fca6831cf2540c36050d4e6 -config_hash: fbf60dd7c0de7e17c7e2bb0ee09e9937 +configured_endpoints: 59 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-85f9d588b888eaac24243e6b71c8ed3b57bba8b28d43bef94d590de60e2d8344.yml +openapi_spec_hash: 7c41d922ada4b7ef51dc0e70005d8d62 +config_hash: 2ebcc80e2cbd2342e132f4474ec24212 diff --git a/README.md b/README.md index 86d6f1f2..7c59c7f3 100644 --- a/README.md +++ b/README.md @@ -220,7 +220,7 @@ const client = createClient({ }); // ... then make API calls as usual. -const accounts = await client.accounts.list(); +const account = await client.accounts.retrieve('accountID'); const chat = await client.chats.create({ accountID: 'accountID', participantIDs: ['string'], @@ -246,7 +246,7 @@ const client: PartialBeeperDesktop<{ accounts: BaseAccounts }> = createClient({ // Function parameter type async function main(client: PartialBeeperDesktop<{ accounts: BaseAccounts }>) { - const accounts = await client.accounts.list(); + const account = await client.accounts.retrieve('accountID'); } // Works with any client that has the accounts resource diff --git a/api.md b/api.md index f0c72a99..90409ce9 100644 --- a/api.md +++ b/api.md @@ -14,6 +14,7 @@ Methods: Types: +- APIError - AppStateSnapshot - Attachment - Error @@ -26,10 +27,13 @@ Types: Types: - Account +- AccountBridge +- AccountRetrieveResponse - AccountListResponse Methods: +- client.accounts.retrieve(accountID) -> AccountRetrieveResponse - client.accounts.list() -> AccountListResponse ## Contacts @@ -47,12 +51,66 @@ Methods: Types: -- BridgeAvailability -- BridgeListResponse +- Bridge +- BridgeConnection +- CookieField +- DisappearingTimerCapability +- GroupFieldCapability +- GroupTypeCapabilities +- LoginFlow +- LoginInputField +- LoginSession +- ProvisioningCapabilities +- ResolveIdentifierCapabilities +- BridgeRetrieveResponse +- BridgeListResponse Methods: -- client.bridges.list() -> BridgeListResponse +- client.bridges.retrieve(bridgeID) -> BridgeRetrieveResponse +- client.bridges.list() -> BridgeListResponse +- client.bridges.retrieveCapabilities(bridgeID) -> ProvisioningCapabilities + +## LoginFlows + +Types: + +- LoginFlowListResponse + +Methods: + +- client.bridges.loginFlows.list(bridgeID) -> LoginFlowListResponse + +## Connections + +Types: + +- ConnectionListResponse +- ConnectionRemoveResponse + +Methods: + +- client.bridges.connections.retrieve(loginID, { ...params }) -> BridgeConnection +- client.bridges.connections.list(bridgeID) -> ConnectionListResponse +- client.bridges.connections.remove(loginID, { ...params }) -> ConnectionRemoveResponse + +## LoginSessions + +Types: + +- LoginSessionCancelResponse + +Methods: + +- client.bridges.loginSessions.create(bridgeID, { ...params }) -> LoginSession +- client.bridges.loginSessions.retrieve(loginSessionID, { ...params }) -> LoginSession +- client.bridges.loginSessions.cancel(loginSessionID, { ...params }) -> LoginSessionCancelResponse + +### Steps + +Methods: + +- client.bridges.loginSessions.steps.submit(stepID, { ...params }) -> LoginSession # Chats @@ -145,233 +203,94 @@ Types: - LoginRegistrationRequiredResponse - LoginResponse - LoginResponseOutput -- RecoveryCodeResetResponse -- StartVerificationResponse -- StateMutationResponse -- AppStatusResponse +- RecoveryKeyResetResponse +- SessionMutationResponse +- Verification +- VerificationResponse +- AppSessionResponse Methods: -- client.app.status() -> AppStatusResponse +- client.app.session() -> AppSessionResponse ## Login Types: -- LoginEmailResponse -- LoginRegisterResponse -- LoginResponseResponse -- LoginStartResponse - -Methods: - -- client.app.login.email({ ...params }) -> unknown -- client.app.login.register({ ...params }) -> LoginRegisterResponse -- client.app.login.response({ ...params }) -> LoginResponseResponse -- client.app.login.start() -> LoginStartResponse - -## E2ee - -### RecoveryCode - -Types: - -- RecoveryCodeMarkBackedUpResponse -- RecoveryCodeVerifyResponse - -Methods: - -- client.app.e2ee.recoveryCode.markBackedUp() -> RecoveryCodeMarkBackedUpResponse -- client.app.e2ee.recoveryCode.verify({ ...params }) -> RecoveryCodeVerifyResponse - -#### Reset - -Types: - -- ResetCreateResponse -- ResetConfirmResponse +- LoginEmailResponse +- LoginRegisterResponse +- LoginResponseResponse +- LoginStartResponse Methods: -- client.app.e2ee.recoveryCode.reset.create({ ...params }) -> ResetCreateResponse -- client.app.e2ee.recoveryCode.reset.confirm({ ...params }) -> ResetConfirmResponse +- client.app.login.email({ ...params }) -> unknown +- client.app.login.register({ ...params }) -> LoginRegisterResponse +- client.app.login.response({ ...params }) -> LoginResponseResponse +- client.app.login.start() -> LoginStartResponse ### Verification -Types: - -- VerificationCreateResponse -- VerificationAcceptResponse -- VerificationCancelResponse - -Methods: - -- client.app.e2ee.verification.create({ ...params }) -> VerificationCreateResponse -- client.app.e2ee.verification.accept(verificationID) -> VerificationAcceptResponse -- client.app.e2ee.verification.cancel(verificationID, { ...params }) -> VerificationCancelResponse - -#### Qr - -Types: - -- QrConfirmScannedResponse -- QrScanResponse - -Methods: - -- client.app.e2ee.verification.qr.confirmScanned(verificationID) -> QrConfirmScannedResponse -- client.app.e2ee.verification.qr.scan({ ...params }) -> QrScanResponse - -#### Sas - -Types: - -- SaConfirmResponse -- SaStartResponse - -Methods: - -- client.app.e2ee.verification.sas.confirm(verificationID) -> SaConfirmResponse -- client.app.e2ee.verification.sas.start(verificationID) -> SaStartResponse - -# Matrix - -## Users - -Types: - -- UserRetrieveProfileResponse - -Methods: - -- client.matrix.users.retrieveProfile(userID) -> UserRetrieveProfileResponse - -### AccountData - -Types: - -- AccountDataRetrieveResponse -- AccountDataUpdateResponse - -Methods: - -- client.matrix.users.accountData.retrieve(type, { ...params }) -> unknown -- client.matrix.users.accountData.update(type, { ...params }) -> unknown - -## Rooms - -Types: - -- RoomCreateResponse -- RoomJoinResponse -- RoomLeaveResponse - -Methods: - -- client.matrix.rooms.create({ ...params }) -> RoomCreateResponse -- client.matrix.rooms.join(roomIDOrAlias, { ...params }) -> RoomJoinResponse -- client.matrix.rooms.leave(roomID, { ...params }) -> unknown - -### AccountData - -Types: - -- AccountDataRetrieveResponse -- AccountDataUpdateResponse - -Methods: - -- client.matrix.rooms.accountData.retrieve(type, { ...params }) -> unknown -- client.matrix.rooms.accountData.update(type, { ...params }) -> unknown - -### State - -Types: - -- StateRetrieveResponse -- StateListResponse - -Methods: - -- client.matrix.rooms.state.retrieve(stateKey, { ...params }) -> StateRetrieveResponse -- client.matrix.rooms.state.list(roomID) -> StateListResponse - -### Events - -Types: - -- EventRetrieveResponse - -Methods: - -- client.matrix.rooms.events.retrieve(eventID, { ...params }) -> EventRetrieveResponse - -## Bridges - -### Auth +#### RecoveryKey Types: -- AuthListFlowsResponse -- AuthListLoginsResponse -- AuthLogoutResponse -- AuthStartLoginResponse -- AuthSubmitCookiesResponse -- AuthSubmitUserInputResponse -- AuthWaitForStepResponse -- AuthWhoamiResponse +- RecoveryKeyVerifyResponse Methods: -- client.matrix.bridges.auth.listFlows(bridgeID) -> AuthListFlowsResponse -- client.matrix.bridges.auth.listLogins(bridgeID) -> AuthListLoginsResponse -- client.matrix.bridges.auth.logout(loginID, { ...params }) -> unknown -- client.matrix.bridges.auth.startLogin(flowID, { ...params }) -> AuthStartLoginResponse -- client.matrix.bridges.auth.submitCookies(stepID, { ...params }) -> AuthSubmitCookiesResponse -- client.matrix.bridges.auth.submitUserInput(stepID, { ...params }) -> AuthSubmitUserInputResponse -- client.matrix.bridges.auth.waitForStep(stepID, { ...params }) -> AuthWaitForStepResponse -- client.matrix.bridges.auth.whoami(bridgeID) -> AuthWhoamiResponse +- client.app.login.verification.recoveryKey.verify({ ...params }) -> RecoveryKeyVerifyResponse -### Contacts +##### Reset Types: -- ContactListResponse +- ResetCreateResponse +- ResetConfirmResponse Methods: -- client.matrix.bridges.contacts.list(bridgeID, { ...params }) -> ContactListResponse +- client.app.login.verification.recoveryKey.reset.create({ ...params }) -> ResetCreateResponse +- client.app.login.verification.recoveryKey.reset.confirm({ ...params }) -> ResetConfirmResponse -### Users +## Verifications Types: -- UserResolveResponse -- UserSearchResponse +- VerificationCreateResponse +- VerificationRetrieveResponse +- VerificationListResponse +- VerificationAcceptResponse +- VerificationCancelResponse Methods: -- client.matrix.bridges.users.resolve(identifier, { ...params }) -> UserResolveResponse -- client.matrix.bridges.users.search(bridgeID, { ...params }) -> UserSearchResponse +- client.app.verifications.create({ ...params }) -> VerificationCreateResponse +- client.app.verifications.retrieve(verificationID) -> VerificationRetrieveResponse +- client.app.verifications.list() -> VerificationListResponse +- client.app.verifications.accept(verificationID) -> VerificationAcceptResponse +- client.app.verifications.cancel(verificationID, { ...params }) -> VerificationCancelResponse -### Rooms +### Qr Types: -- RoomCreateDmResponse -- RoomCreateGroupResponse +- QrConfirmScannedResponse +- QrScanResponse Methods: -- client.matrix.bridges.rooms.createDm(identifier, { ...params }) -> RoomCreateDmResponse -- client.matrix.bridges.rooms.createGroup(groupType, { ...params }) -> RoomCreateGroupResponse +- client.app.verifications.qr.confirmScanned(verificationID) -> QrConfirmScannedResponse +- client.app.verifications.qr.scan({ ...params }) -> QrScanResponse -### Capabilities +### SAS Types: -- CapabilityRetrieveResponse +- SASConfirmResponse +- SASStartResponse Methods: -- client.matrix.bridges.capabilities.retrieve(bridgeID) -> CapabilityRetrieveResponse +- client.app.verifications.sas.confirm(verificationID) -> SASConfirmResponse +- client.app.verifications.sas.start(verificationID) -> SASStartResponse diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index 0a679b43..efe17bd5 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -111,9 +111,20 @@ const fuse = new Fuse( 'client.focus', 'client.search', 'client.accounts.list', + 'client.accounts.retrieve', 'client.accounts.contacts.list', 'client.accounts.contacts.search', 'client.bridges.list', + 'client.bridges.retrieve', + 'client.bridges.retrieveCapabilities', + 'client.bridges.loginFlows.list', + 'client.bridges.connections.list', + 'client.bridges.connections.remove', + 'client.bridges.connections.retrieve', + 'client.bridges.loginSessions.cancel', + 'client.bridges.loginSessions.create', + 'client.bridges.loginSessions.retrieve', + 'client.bridges.loginSessions.steps.submit', 'client.chats.archive', 'client.chats.create', 'client.chats.list', @@ -139,47 +150,23 @@ const fuse = new Fuse( 'client.assets.upload', 'client.assets.uploadBase64', 'client.info.retrieve', - 'client.app.status', + 'client.app.session', 'client.app.login.email', 'client.app.login.register', 'client.app.login.response', 'client.app.login.start', - 'client.app.e2ee.recoveryCode.markBackedUp', - 'client.app.e2ee.recoveryCode.verify', - 'client.app.e2ee.recoveryCode.reset.confirm', - 'client.app.e2ee.recoveryCode.reset.create', - 'client.app.e2ee.verification.accept', - 'client.app.e2ee.verification.cancel', - 'client.app.e2ee.verification.create', - 'client.app.e2ee.verification.qr.confirmScanned', - 'client.app.e2ee.verification.qr.scan', - 'client.app.e2ee.verification.sas.confirm', - 'client.app.e2ee.verification.sas.start', - 'client.matrix.users.retrieveProfile', - 'client.matrix.users.accountData.retrieve', - 'client.matrix.users.accountData.update', - 'client.matrix.rooms.create', - 'client.matrix.rooms.join', - 'client.matrix.rooms.leave', - 'client.matrix.rooms.accountData.retrieve', - 'client.matrix.rooms.accountData.update', - 'client.matrix.rooms.state.list', - 'client.matrix.rooms.state.retrieve', - 'client.matrix.rooms.events.retrieve', - 'client.matrix.bridges.auth.listFlows', - 'client.matrix.bridges.auth.listLogins', - 'client.matrix.bridges.auth.logout', - 'client.matrix.bridges.auth.startLogin', - 'client.matrix.bridges.auth.submitCookies', - 'client.matrix.bridges.auth.submitUserInput', - 'client.matrix.bridges.auth.waitForStep', - 'client.matrix.bridges.auth.whoami', - 'client.matrix.bridges.contacts.list', - 'client.matrix.bridges.users.resolve', - 'client.matrix.bridges.users.search', - 'client.matrix.bridges.rooms.createDm', - 'client.matrix.bridges.rooms.createGroup', - 'client.matrix.bridges.capabilities.retrieve', + 'client.app.login.verification.recoveryKey.verify', + 'client.app.login.verification.recoveryKey.reset.confirm', + 'client.app.login.verification.recoveryKey.reset.create', + 'client.app.verifications.accept', + 'client.app.verifications.cancel', + 'client.app.verifications.create', + 'client.app.verifications.list', + 'client.app.verifications.retrieve', + 'client.app.verifications.qr.confirmScanned', + 'client.app.verifications.qr.scan', + 'client.app.verifications.sas.confirm', + 'client.app.verifications.sas.start', ], { threshold: 1, shouldSort: true }, ); diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index c287423d..6c2400db 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -86,7 +86,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, cli: { method: '$client focus', - example: "beeper-desktop-cli focus \\\n --access-token 'My Access Token'", + example: "beeper-desktop focus \\\n --access-token 'My Access Token'", }, php: { method: 'focus', @@ -131,7 +131,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, cli: { method: '$client search', - example: "beeper-desktop-cli search \\\n --access-token 'My Access Token' \\\n --query x", + example: "beeper-desktop search \\\n --access-token 'My Access Token' \\\n --query x", }, php: { method: 'search', @@ -154,9 +154,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ stainlessPath: '(resource) accounts > (method) list', qualified: 'client.accounts.list', response: - "{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]", + '{ accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]', markdown: - "## list\n\n`client.accounts.list(): object[]`\n\n**get** `/v1/accounts`\n\nList Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.\n\n### Returns\n\n- `{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; user: object; network?: string; }[]`\n Accounts configured on this device. Includes accountID, bridge metadata, optional network name, and user identity.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);\n```", + "## list\n\n`client.accounts.list(): object[]`\n\n**get** `/v1/accounts`\n\nList Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.\n\n### Returns\n\n- `{ accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]`\n Accounts configured on this device. Includes accountID, bridge metadata, optional network name, and user identity.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);\n```", perLanguage: { typescript: { method: 'client.accounts.list', @@ -175,7 +175,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, cli: { method: 'accounts list', - example: "beeper-desktop-cli accounts list \\\n --access-token 'My Access Token'", + example: "beeper-desktop accounts list \\\n --access-token 'My Access Token'", }, php: { method: 'accounts->list', @@ -188,6 +188,51 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, }, }, + { + name: 'retrieve', + endpoint: '/v1/accounts/{accountID}', + httpMethod: 'get', + summary: 'Get Chat Account', + description: 'Get one Chat Account connected to this Beeper Desktop instance.', + stainlessPath: '(resource) accounts > (method) retrieve', + qualified: 'client.accounts.retrieve', + params: ['accountID: string;'], + response: + "{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }", + markdown: + "## retrieve\n\n`client.accounts.retrieve(accountID: string): { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n\n**get** `/v1/accounts/{accountID}`\n\nGet one Chat Account connected to this Beeper Desktop instance.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n### Returns\n\n- `{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n A chat account added to Beeper.\n\n - `accountID: string`\n - `bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }`\n - `status: string`\n - `user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n - `capabilities?: object`\n - `loginID?: string`\n - `network?: string`\n - `statusText?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst account = await client.accounts.retrieve('accountID');\n\nconsole.log(account);\n```", + perLanguage: { + typescript: { + method: 'client.accounts.retrieve', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst account = await client.accounts.retrieve('accountID');\n\nconsole.log(account.bridge);", + }, + python: { + method: 'accounts.retrieve', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount = client.accounts.retrieve(\n "accountID",\n)\nprint(account.bridge)', + }, + go: { + method: 'client.Accounts.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccount, err := client.Accounts.Get(context.TODO(), "accountID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", account.Bridge)\n}\n', + }, + cli: { + method: 'accounts retrieve', + example: + "beeper-desktop accounts retrieve \\\n --access-token 'My Access Token' \\\n --account-id accountID", + }, + php: { + method: 'accounts->retrieve', + example: + "accounts->retrieve('accountID');\n\nvar_dump($account);", + }, + http: { + example: + 'curl http://localhost:23373/v1/accounts/$ACCOUNT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, { name: 'search', endpoint: '/v1/accounts/{accountID}/contacts', @@ -221,7 +266,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ cli: { method: 'contacts search', example: - "beeper-desktop-cli accounts:contacts search \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --query x", + "beeper-desktop accounts:contacts search \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --query x", }, php: { method: 'accounts->contacts->search', @@ -272,7 +317,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ cli: { method: 'contacts list', example: - "beeper-desktop-cli accounts:contacts list \\\n --access-token 'My Access Token' \\\n --account-id accountID", + "beeper-desktop accounts:contacts list \\\n --access-token 'My Access Token' \\\n --account-id accountID", }, php: { method: 'accounts->contacts->list', @@ -295,9 +340,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ stainlessPath: '(resource) bridges > (method) list', qualified: 'client.bridges.list', response: - "{ items: { accounts: account[]; activeAccountCount: number; bridge: object; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]; }", + "{ items: { id: string; accounts: account[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }[]; }", markdown: - "## list\n\n`client.bridges.list(): { items: bridge_availability[]; }`\n\n**get** `/v1/bridges`\n\nList bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.\n\n### Returns\n\n- `{ items: { accounts: account[]; activeAccountCount: number; bridge: object; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]; }`\n Bridge-backed account types and their connected accounts.\n\n - `items: { accounts: { accountID: string; bridge: object; user: user; network?: string; }[]; activeAccountCount: number; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; displayName: string; loginMode: string; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; network?: string; statusText?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges);\n```", + "## list\n\n`client.bridges.list(): { items: bridge[]; }`\n\n**get** `/v1/bridges`\n\nList bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.\n\n### Returns\n\n- `{ items: { id: string; accounts: account[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }[]; }`\n Bridge-backed account types and their connected accounts.\n\n - `items: { id: string; accounts: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges);\n```", perLanguage: { typescript: { method: 'client.bridges.list', @@ -316,7 +361,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, cli: { method: 'bridges list', - example: "beeper-desktop-cli bridges list \\\n --access-token 'My Access Token'", + example: "beeper-desktop bridges list \\\n --access-token 'My Access Token'", }, php: { method: 'bridges->list', @@ -331,3048 +376,2391 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, { name: 'retrieve', - endpoint: '/v1/chats/{chatID}', + endpoint: '/v1/bridges/{bridgeID}', httpMethod: 'get', - summary: 'Retrieve chat details', - description: 'Retrieve chat details including metadata, participants, and latest message', - stainlessPath: '(resource) chats > (method) retrieve', - qualified: 'client.chats.retrieve', - params: ['chatID: string;', 'maxParticipantCount?: number;'], + summary: 'Get bridge', + description: 'Get one bridge-backed account type and the connected accounts that use it.', + stainlessPath: '(resource) bridges > (method) retrieve', + qualified: 'client.bridges.retrieve', + params: ['bridgeID: string;'], response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + "{ id: string; accounts: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }", markdown: - "## retrieve\n\n`client.chats.retrieve(chatID: string, maxParticipantCount?: number): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/{chatID}`\n\nRetrieve chat details including metadata, participants, and latest message\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `maxParticipantCount?: number`\n 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.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## retrieve\n\n`client.bridges.retrieve(bridgeID: string): { id: string; accounts: account[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }`\n\n**get** `/v1/bridges/{bridgeID}`\n\nGet one bridge-backed account type and the connected accounts that use it.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ id: string; accounts: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }`\n Bridge-backed account type that can be shown in add-account flows.\n\n - `id: string`\n - `accounts: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]`\n - `activeAccountCount: number`\n - `displayName: string`\n - `provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'`\n - `status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'`\n - `supportsMultipleAccounts: boolean`\n - `type: string`\n - `network?: string`\n - `statusText?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridge = await client.bridges.retrieve('local-whatsapp');\n\nconsole.log(bridge);\n```", perLanguage: { typescript: { - method: 'client.chats.retrieve', + method: 'client.bridges.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst bridge = await client.bridges.retrieve('local-whatsapp');\n\nconsole.log(bridge.id);", }, python: { - method: 'chats.retrieve', + method: 'bridges.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.retrieve(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nbridge = client.bridges.retrieve(\n "local-whatsapp",\n)\nprint(bridge.id)', }, go: { - method: 'client.Chats.Get', + method: 'client.Bridges.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Get(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatGetParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tbridge, err := client.Bridges.Get(context.TODO(), "local-whatsapp")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", bridge.ID)\n}\n', }, cli: { - method: 'chats retrieve', + method: 'bridges retrieve', example: - "beeper-desktop-cli chats retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop bridges retrieve \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp", }, php: { - method: 'chats->retrieve', + method: 'bridges->retrieve', example: - "chats->retrieve(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', maxParticipantCount: 100\n);\n\nvar_dump($chat);", + "bridges->retrieve('local-whatsapp');\n\nvar_dump($bridge);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'create', - endpoint: '/v1/chats', - httpMethod: 'post', - summary: 'Create a chat', - description: 'Create a direct or group chat from participant IDs. Returns the created chat.', - stainlessPath: '(resource) chats > (method) create', - qualified: 'client.chats.create', - params: [ - 'accountID: string;', - 'participantIDs: string[];', - "type: 'single' | 'group';", - 'messageText?: string;', - 'title?: string;', - ], + name: 'retrieve_capabilities', + endpoint: '/v1/bridges/{bridgeID}/capabilities', + httpMethod: 'get', + summary: 'Get bridge capabilities', + description: 'Get bridgev2 provisioning capabilities for a bridge.', + stainlessPath: '(resource) bridges > (method) retrieve_capabilities', + qualified: 'client.bridges.retrieveCapabilities', + params: ['bridgeID: string;'], response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + '{ group_creation: object; resolve_identifier: { any_phone: boolean; contact_list: boolean; create_dm: boolean; lookup_email: boolean; lookup_phone: boolean; lookup_username: boolean; search: boolean; }; image_pack_import?: boolean; }', markdown: - "## create\n\n`client.chats.create(accountID: string, participantIDs: string[], type: 'single' | 'group', messageText?: string, title?: string): object`\n\n**post** `/v1/chats`\n\nCreate a direct or group chat from participant IDs. Returns the created chat.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `participantIDs: string[]`\n User IDs to include in the new chat.\n\n- `type: 'single' | 'group'`\n 'single' requires exactly one participantID; 'group' supports multiple participants and optional title.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n- `title?: string`\n Optional title for group chats; ignored for single chats on most networks.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.create({\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n});\n\nconsole.log(chat);\n```", + "## retrieve_capabilities\n\n`client.bridges.retrieveCapabilities(bridgeID: string): { group_creation: object; resolve_identifier: resolve_identifier_capabilities; image_pack_import?: boolean; }`\n\n**get** `/v1/bridges/{bridgeID}/capabilities`\n\nGet bridgev2 provisioning capabilities for a bridge.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ group_creation: object; resolve_identifier: { any_phone: boolean; contact_list: boolean; create_dm: boolean; lookup_email: boolean; lookup_phone: boolean; lookup_username: boolean; search: boolean; }; image_pack_import?: boolean; }`\n bridgev2 provisioning capabilities.\n\n - `group_creation: object`\n - `resolve_identifier: { any_phone: boolean; contact_list: boolean; create_dm: boolean; lookup_email: boolean; lookup_phone: boolean; lookup_username: boolean; search: boolean; }`\n - `image_pack_import?: boolean`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst provisioningCapabilities = await client.bridges.retrieveCapabilities('local-whatsapp');\n\nconsole.log(provisioningCapabilities);\n```", perLanguage: { typescript: { - method: 'client.chats.create', + method: 'client.bridges.retrieveCapabilities', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.create({\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n});\n\nconsole.log(chat);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst provisioningCapabilities = await client.bridges.retrieveCapabilities('local-whatsapp');\n\nconsole.log(provisioningCapabilities.resolve_identifier);", }, python: { - method: 'chats.create', + method: 'bridges.retrieve_capabilities', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.create(\n account_id="accountID",\n participant_ids=["string"],\n type="single",\n)\nprint(chat)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nprovisioning_capabilities = client.bridges.retrieve_capabilities(\n "local-whatsapp",\n)\nprint(provisioning_capabilities.resolve_identifier)', }, go: { - method: 'client.Chats.New', + method: 'client.Bridges.GetCapabilities', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.New(context.TODO(), beeperdesktopapi.ChatNewParams{\n\t\tAccountID: "accountID",\n\t\tParticipantIDs: []string{"string"},\n\t\tType: beeperdesktopapi.ChatNewParamsTypeSingle,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tprovisioningCapabilities, err := client.Bridges.GetCapabilities(context.TODO(), "local-whatsapp")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", provisioningCapabilities.ResolveIdentifier)\n}\n', }, cli: { - method: 'chats create', + method: 'bridges retrieve_capabilities', example: - "beeper-desktop-cli chats create \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --participant-id string \\\n --type single", + "beeper-desktop bridges retrieve-capabilities \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp", }, php: { - method: 'chats->create', + method: 'bridges->retrieveCapabilities', example: - "chats->create(\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n messageText: 'messageText',\n title: 'title',\n);\n\nvar_dump($chat);", + "bridges->retrieveCapabilities(\n 'local-whatsapp'\n);\n\nvar_dump($provisioningCapabilities);", }, http: { example: - 'curl http://localhost:23373/v1/chats \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "accountID": "accountID",\n "participantIDs": [\n "string"\n ],\n "type": "single"\n }\'', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/capabilities \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'start', - endpoint: '/v1/chats/start', - httpMethod: '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+.', - stainlessPath: '(resource) chats > (method) start', - qualified: 'client.chats.start', - params: [ - 'accountID: string;', - 'user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; };', - 'allowInvite?: boolean;', - 'messageText?: string;', - ], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + name: 'list', + endpoint: '/v1/bridges/{bridgeID}/login-flows', + httpMethod: 'get', + summary: 'List bridge login flows', + description: 'List bridge login flows that can be used to start a bridge login session.', + stainlessPath: '(resource) bridges.login_flows > (method) list', + qualified: 'client.bridges.loginFlows.list', + params: ['bridgeID: string;'], + response: '{ items: { id: string; description?: string; name?: string; }[]; }', markdown: - "## start\n\n`client.chats.start(accountID: string, user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }, allowInvite?: boolean, messageText?: string): object`\n\n**post** `/v1/chats/start`\n\nResolve 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+.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }`\n Merged user-like contact payload used to resolve the best identifier.\n - `id?: string`\n Known user ID when available.\n - `email?: string`\n Email candidate.\n - `fullName?: string`\n Display name hint used for ranking only.\n - `phoneNumber?: string`\n Phone number candidate (E.164 preferred).\n - `username?: string`\n Username/handle candidate.\n\n- `allowInvite?: boolean`\n Whether invite-based DM creation is allowed when required by the platform.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);\n```", + "## list\n\n`client.bridges.loginFlows.list(bridgeID: string): { items: login_flow[]; }`\n\n**get** `/v1/bridges/{bridgeID}/login-flows`\n\nList bridge login flows that can be used to start a bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ items: { id: string; description?: string; name?: string; }[]; }`\n\n - `items: { id: string; description?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginFlows = await client.bridges.loginFlows.list('local-whatsapp');\n\nconsole.log(loginFlows);\n```", perLanguage: { typescript: { - method: 'client.chats.start', + method: 'client.bridges.loginFlows.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst loginFlows = await client.bridges.loginFlows.list('local-whatsapp');\n\nconsole.log(loginFlows.items);", }, python: { - method: 'chats.start', + method: 'bridges.login_flows.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.chats.start(\n account_id="accountID",\n user={},\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nlogin_flows = client.bridges.login_flows.list(\n "local-whatsapp",\n)\nprint(login_flows.items)', }, go: { - method: 'client.Chats.Start', + method: 'client.Bridges.LoginFlows.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Start(context.TODO(), beeperdesktopapi.ChatStartParams{\n\t\tAccountID: "accountID",\n\t\tUser: beeperdesktopapi.ChatStartParamsUser{},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tloginFlows, err := client.Bridges.LoginFlows.List(context.TODO(), "local-whatsapp")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", loginFlows.Items)\n}\n', }, cli: { - method: 'chats start', + method: 'login_flows list', example: - "beeper-desktop-cli chats start \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --user '{}'", + "beeper-desktop bridges:login-flows list \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp", }, php: { - method: 'chats->start', + method: 'bridges->loginFlows->list', example: - "chats->start(\n accountID: 'accountID',\n user: [\n 'id' => 'id',\n 'email' => 'email',\n 'fullName' => 'fullName',\n 'phoneNumber' => 'phoneNumber',\n 'username' => 'username',\n ],\n allowInvite: true,\n messageText: 'messageText',\n);\n\nvar_dump($response);", + "bridges->loginFlows->list('local-whatsapp');\n\nvar_dump($loginFlows);", }, http: { example: - 'curl http://localhost:23373/v1/chats/start \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "accountID": "accountID",\n "user": {}\n }\'', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/login-flows \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { name: 'list', - endpoint: '/v1/chats', + endpoint: '/v1/bridges/{bridgeID}/connections', httpMethod: 'get', - summary: 'List chats', - description: - 'List all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.', - stainlessPath: '(resource) chats > (method) list', - qualified: 'client.chats.list', - params: ['accountIDs?: string[];', 'cursor?: string;', "direction?: 'after' | 'before';"], + summary: 'List bridge connections', + description: 'List durable bridge connection identities for a bridge.', + stainlessPath: '(resource) bridges.connections > (method) list', + qualified: 'client.bridges.connections.list', + params: ['bridgeID: string;'], response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + "{ items: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }[]; }", markdown: - "## list\n\n`client.chats.list(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before'): object`\n\n**get** `/v1/chats`\n\nList all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit to specific account IDs. If omitted, fetches from all accounts.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n Chat with optional last message preview.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chatListResponse of client.chats.list()) {\n console.log(chatListResponse);\n}\n```", + "## list\n\n`client.bridges.connections.list(bridgeID: string): { items: bridge_connection[]; }`\n\n**get** `/v1/bridges/{bridgeID}/connections`\n\nList durable bridge connection identities for a bridge.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ items: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }[]; }`\n\n - `items: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst connections = await client.bridges.connections.list('local-whatsapp');\n\nconsole.log(connections);\n```", perLanguage: { typescript: { - method: 'client.chats.list', + method: 'client.bridges.connections.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const chatListResponse of client.chats.list()) {\n console.log(chatListResponse);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst connections = await client.bridges.connections.list('local-whatsapp');\n\nconsole.log(connections.items);", }, python: { - method: 'chats.list', + method: 'bridges.connections.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.chats.list()\npage = page.items[0]\nprint(page)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nconnections = client.bridges.connections.list(\n "local-whatsapp",\n)\nprint(connections.items)', }, go: { - method: 'client.Chats.List', + method: 'client.Bridges.Connections.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.List(context.TODO(), beeperdesktopapi.ChatListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tconnections, err := client.Bridges.Connections.List(context.TODO(), "local-whatsapp")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", connections.Items)\n}\n', }, cli: { - method: 'chats list', - example: "beeper-desktop-cli chats list \\\n --access-token 'My Access Token'", + method: 'connections list', + example: + "beeper-desktop bridges:connections list \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp", }, php: { - method: 'chats->list', + method: 'bridges->connections->list', example: - "chats->list(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n);\n\nvar_dump($page);", + "bridges->connections->list('local-whatsapp');\n\nvar_dump($connections);", }, http: { example: - 'curl http://localhost:23373/v1/chats \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/connections \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'search', - endpoint: '/v1/chats/search', + name: 'retrieve', + endpoint: '/v1/bridges/{bridgeID}/connections/{loginID}', httpMethod: 'get', - summary: 'Search chats', - description: 'Search chats by title, network, or participant names.', - stainlessPath: '(resource) chats > (method) search', - qualified: 'client.chats.search', - params: [ - 'accountIDs?: string[];', - 'cursor?: string;', - "direction?: 'after' | 'before';", - "inbox?: 'primary' | 'low-priority' | 'archive';", - 'includeMuted?: boolean;', - 'lastActivityAfter?: string;', - 'lastActivityBefore?: string;', - 'limit?: number;', - 'query?: string;', - "scope?: 'titles' | 'participants';", - "type?: 'single' | 'group' | 'any';", - 'unreadOnly?: boolean;', - ], + summary: 'Get bridge connection', + description: 'Get one durable bridge connection identity.', + stainlessPath: '(resource) bridges.connections > (method) retrieve', + qualified: 'client.bridges.connections.retrieve', + params: ['bridgeID: string;', 'loginID: string;'], response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + "{ bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }", markdown: - "## search\n\n`client.chats.search(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before', inbox?: 'primary' | 'low-priority' | 'archive', includeMuted?: boolean, lastActivityAfter?: string, lastActivityBefore?: string, limit?: number, query?: string, scope?: 'titles' | 'participants', type?: 'single' | 'group' | 'any', unreadOnly?: boolean): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/search`\n\nSearch chats by title, network, or participant names.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Provide an array of account IDs to filter chats from specific messaging accounts only\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `inbox?: 'primary' | 'low-priority' | 'archive'`\n Filter by inbox type: \"primary\" (non-archived, non-low-priority), \"low-priority\", or \"archive\". If not specified, shows all chats.\n\n- `includeMuted?: boolean`\n 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.\n\n- `lastActivityAfter?: string`\n Provide an ISO datetime string to only retrieve chats with last activity after this time\n\n- `lastActivityBefore?: string`\n Provide an ISO datetime string to only retrieve chats with last activity before this time\n\n- `limit?: number`\n Set the maximum number of chats to retrieve. Valid range: 1-200, default is 50\n\n- `query?: string`\n Literal token search (non-semantic). Use single words users type (e.g., \"dinner\"). When multiple words provided, ALL must match. Case-insensitive.\n\n- `scope?: 'titles' | 'participants'`\n Search scope: 'titles' matches title + network; 'participants' matches participant names.\n\n- `type?: 'single' | 'group' | 'any'`\n Specify the type of chats to retrieve: use \"single\" for direct messages, \"group\" for group chats, or \"any\" to get all types\n\n- `unreadOnly?: boolean`\n Set to true to only retrieve chats that have unread messages\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat);\n}\n```", + "## retrieve\n\n`client.bridges.connections.retrieve(bridgeID: string, loginID: string): { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }`\n\n**get** `/v1/bridges/{bridgeID}/connections/{loginID}`\n\nGet one durable bridge connection identity.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginID: string`\n Bridge login ID.\n\n### Returns\n\n- `{ bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n Durable bridge connection identity. This is not guaranteed to be one-to-one with a Desktop API account.\n\n - `bridgeID: string`\n - `loginID: string`\n - `removeScopes: 'current-device' | 'all-devices'[]`\n - `status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'`\n - `accountIDs?: string[]`\n - `statusText?: string`\n - `user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridgeConnection = await client.bridges.connections.retrieve('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { bridgeID: 'local-whatsapp' });\n\nconsole.log(bridgeConnection);\n```", perLanguage: { typescript: { - method: 'client.chats.search', + method: 'client.bridges.connections.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat.id);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst bridgeConnection = await client.bridges.connections.retrieve(\n 'ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc',\n { bridgeID: 'local-whatsapp' },\n);\n\nconsole.log(bridgeConnection.bridgeID);", }, python: { - method: 'chats.search', + method: 'bridges.connections.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.chats.search()\npage = page.items[0]\nprint(page.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nbridge_connection = client.bridges.connections.retrieve(\n login_id="ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc",\n bridge_id="local-whatsapp",\n)\nprint(bridge_connection.bridge_id)', }, go: { - method: 'client.Chats.Search', + method: 'client.Bridges.Connections.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.Search(context.TODO(), beeperdesktopapi.ChatSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tbridgeConnection, err := client.Bridges.Connections.Get(\n\t\tcontext.TODO(),\n\t\t"ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc",\n\t\tbeeperdesktopapi.BridgeConnectionGetParams{\n\t\t\tBridgeID: "local-whatsapp",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", bridgeConnection.BridgeID)\n}\n', }, cli: { - method: 'chats search', - example: "beeper-desktop-cli chats search \\\n --access-token 'My Access Token'", + method: 'connections retrieve', + example: + "beeper-desktop bridges:connections retrieve \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp \\\n --login-id ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc", }, php: { - method: 'chats->search', + method: 'bridges->connections->retrieve', example: - "chats->search(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n inbox: 'primary',\n includeMuted: true,\n lastActivityAfter: new \\DateTimeImmutable('2019-12-27T18:11:19.117Z'),\n lastActivityBefore: new \\DateTimeImmutable('2019-12-27T18:11:19.117Z'),\n limit: 1,\n query: 'x',\n scope: 'titles',\n type: 'single',\n unreadOnly: true,\n);\n\nvar_dump($page);", + "bridges->connections->retrieve(\n 'ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', bridgeID: 'local-whatsapp'\n);\n\nvar_dump($bridgeConnection);", }, http: { example: - 'curl http://localhost:23373/v1/chats/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/connections/$LOGIN_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'archive', - endpoint: '/v1/chats/{chatID}/archive', + name: 'remove', + endpoint: '/v1/bridges/{bridgeID}/connections/{loginID}/remove', httpMethod: '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', - stainlessPath: '(resource) chats > (method) archive', - qualified: 'client.chats.archive', - params: ['chatID: string;', 'archived?: boolean;'], + summary: 'Remove bridge connection', + description: 'Remove a bridge connection from this device or from all devices.', + stainlessPath: '(resource) bridges.connections > (method) remove', + qualified: 'client.bridges.connections.remove', + params: ['bridgeID: string;', 'loginID: string;', "scope: 'current-device' | 'all-devices';"], + response: + "{ bridgeID: string; loginID: string; scope: 'current-device' | 'all-devices'; status: 'removed'; affectedAccountIDs?: string[]; }", markdown: - "## archive\n\n`client.chats.archive(chatID: string, archived?: boolean): void`\n\n**post** `/v1/chats/{chatID}/archive`\n\nArchive or unarchive a chat. Set archived=true to move to archive, archived=false to move back to inbox\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `archived?: boolean`\n True to archive, false to unarchive\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", + "## remove\n\n`client.bridges.connections.remove(bridgeID: string, loginID: string, scope: 'current-device' | 'all-devices'): { bridgeID: string; loginID: string; scope: 'current-device' | 'all-devices'; status: 'removed'; affectedAccountIDs?: string[]; }`\n\n**post** `/v1/bridges/{bridgeID}/connections/{loginID}/remove`\n\nRemove a bridge connection from this device or from all devices.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginID: string`\n Bridge login ID.\n\n- `scope: 'current-device' | 'all-devices'`\n Where this bridge connection should be removed.\n\n### Returns\n\n- `{ bridgeID: string; loginID: string; scope: 'current-device' | 'all-devices'; status: 'removed'; affectedAccountIDs?: string[]; }`\n\n - `bridgeID: string`\n - `loginID: string`\n - `scope: 'current-device' | 'all-devices'`\n - `status: 'removed'`\n - `affectedAccountIDs?: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst connection = await client.bridges.connections.remove('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { bridgeID: 'local-whatsapp', scope: 'current-device' });\n\nconsole.log(connection);\n```", perLanguage: { typescript: { - method: 'client.chats.archive', + method: 'client.bridges.connections.remove', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com');", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst connection = await client.bridges.connections.remove('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', {\n bridgeID: 'local-whatsapp',\n scope: 'current-device',\n});\n\nconsole.log(connection.bridgeID);", }, python: { - method: 'chats.archive', + method: 'bridges.connections.remove', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.archive(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nconnection = client.bridges.connections.remove(\n login_id="ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc",\n bridge_id="local-whatsapp",\n scope="current-device",\n)\nprint(connection.bridge_id)', }, go: { - method: 'client.Chats.Archive', + method: 'client.Bridges.Connections.Remove', example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Archive(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatArchiveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tconnection, err := client.Bridges.Connections.Remove(\n\t\tcontext.TODO(),\n\t\t"ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc",\n\t\tbeeperdesktopapi.BridgeConnectionRemoveParams{\n\t\t\tBridgeID: "local-whatsapp",\n\t\t\tScope: beeperdesktopapi.BridgeConnectionRemoveParamsScopeCurrentDevice,\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", connection.BridgeID)\n}\n', }, cli: { - method: 'chats archive', + method: 'connections remove', example: - "beeper-desktop-cli chats archive \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop bridges:connections remove \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp \\\n --login-id ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --scope current-device", }, php: { - method: 'chats->archive', + method: 'bridges->connections->remove', example: - "chats->archive(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', archived: true\n);\n\nvar_dump($result);", + "bridges->connections->remove(\n 'ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc',\n bridgeID: 'local-whatsapp',\n scope: 'current-device',\n);\n\nvar_dump($connection);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/archive \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/connections/$LOGIN_ID/remove \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "scope": "current-device"\n }\'', }, }, }, { - name: 'update', - endpoint: '/v1/chats/{chatID}', - httpMethod: 'patch', - summary: 'Update chat', + name: 'create', + endpoint: '/v1/bridges/{bridgeID}/login-sessions', + httpMethod: 'post', + summary: 'Create bridge login session', 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.', - stainlessPath: '(resource) chats > (method) update', - qualified: 'client.chats.update', - params: [ - 'chatID: string;', - 'description?: string;', - 'draft?: { text: string; attachments?: object; };', - 'imgURL?: string;', - 'isArchived?: boolean;', - 'isLowPriority?: boolean;', - 'isMuted?: boolean;', - 'isPinned?: boolean;', - 'messageExpirySeconds?: number;', - 'title?: string;', - ], + 'Start an add-account or reconnect flow for a bridge. Omit loginID/accountID to add a new account.', + stainlessPath: '(resource) bridges.login_sessions > (method) create', + qualified: 'client.bridges.loginSessions.create', + params: ['bridgeID: string;', 'accountID?: string;', 'flowID?: string;', 'loginID?: string;'], response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + "{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }", markdown: - "## update\n\n`client.chats.update(chatID: string, description?: string, draft?: { text: string; attachments?: object; }, imgURL?: string, isArchived?: boolean, isLowPriority?: boolean, isMuted?: boolean, isPinned?: boolean, messageExpirySeconds?: number, title?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**patch** `/v1/chats/{chatID}`\n\nUpdate 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.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `description?: string`\n Group chat description/topic. Support depends on the chat account and chat permissions.\n\n- `draft?: { text: string; attachments?: object; }`\n Draft object to set or clear. Non-empty drafts are only accepted when the current draft is empty. Send draft=null to clear text and attachments together before setting a new draft.\n - `text: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n - `attachments?: object`\n Draft attachments keyed by attachment ID. Each attachment must reference an uploadID returned by the upload file endpoint.\n\n- `imgURL?: string`\n Local filesystem path to a group chat avatar image. Support depends on the chat account and chat permissions.\n\n- `isArchived?: boolean`\n Archive or unarchive the chat.\n\n- `isLowPriority?: boolean`\n Mark or unmark the chat as low priority when supported by the account.\n\n- `isMuted?: boolean`\n Mute or unmute the chat.\n\n- `isPinned?: boolean`\n Pin or unpin the chat when supported by the account.\n\n- `messageExpirySeconds?: number`\n Disappearing-message timer in seconds, or null to clear when supported.\n\n- `title?: string`\n Custom chat title. Support depends on the chat account and chat permissions.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## create\n\n`client.bridges.loginSessions.create(bridgeID: string, accountID?: string, flowID?: string, loginID?: string): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; connection?: bridge_connection; currentStep?: object | object | object | object; error?: api_error; loginID?: string; }`\n\n**post** `/v1/bridges/{bridgeID}/login-sessions`\n\nStart an add-account or reconnect flow for a bridge. Omit loginID/accountID to add a new account.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `accountID?: string`\n\n- `flowID?: string`\n\n- `loginID?: string`\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; instructions?: string; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.create('local-whatsapp');\n\nconsole.log(loginSession);\n```", perLanguage: { typescript: { - method: 'client.chats.update', + method: 'client.bridges.loginSessions.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst loginSession = await client.bridges.loginSessions.create('local-whatsapp');\n\nconsole.log(loginSession.bridgeID);", }, python: { - method: 'chats.update', + method: 'bridges.login_sessions.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.update(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nlogin_session = client.bridges.login_sessions.create(\n bridge_id="local-whatsapp",\n)\nprint(login_session.bridge_id)', }, go: { - method: 'client.Chats.Update', + method: 'client.Bridges.LoginSessions.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Update(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tloginSession, err := client.Bridges.LoginSessions.New(\n\t\tcontext.TODO(),\n\t\t"local-whatsapp",\n\t\tbeeperdesktopapi.BridgeLoginSessionNewParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", loginSession.BridgeID)\n}\n', }, cli: { - method: 'chats update', + method: 'login_sessions create', example: - "beeper-desktop-cli chats update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop bridges:login-sessions create \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp", }, php: { - method: 'chats->update', + method: 'bridges->loginSessions->create', example: - "chats->update(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n description: 'description',\n draft: [\n 'text' => 'text',\n 'attachments' => [\n 'foo' => [\n 'uploadID' => 'uploadID',\n 'id' => 'id',\n 'duration' => 0,\n 'fileName' => 'fileName',\n 'mimeType' => 'mimeType',\n 'size' => ['height' => 0, 'width' => 0],\n 'type' => 'image',\n ],\n ],\n ],\n imgURL: 'imgURL',\n isArchived: true,\n isLowPriority: true,\n isMuted: true,\n isPinned: true,\n messageExpirySeconds: 0,\n title: 'title',\n);\n\nvar_dump($chat);", + "bridges->loginSessions->create(\n 'local-whatsapp', accountID: 'accountID', flowID: 'flowID', loginID: 'loginID'\n);\n\nvar_dump($loginSession);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID \\\n -X PATCH \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/login-sessions \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'mark_read', - endpoint: '/v1/chats/{chatID}/read', - httpMethod: 'post', - summary: 'Mark a chat as read', - description: 'Mark a chat as read, optionally through a specific message ID.', - stainlessPath: '(resource) chats > (method) mark_read', - qualified: 'client.chats.markRead', - params: ['chatID: string;', 'messageID?: string;'], + name: 'retrieve', + endpoint: '/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}', + httpMethod: 'get', + summary: 'Get bridge login session', + description: 'Get the current state of a temporary bridge login session.', + stainlessPath: '(resource) bridges.login_sessions > (method) retrieve', + qualified: 'client.bridges.loginSessions.retrieve', + params: ['bridgeID: string;', 'loginSessionID: string;'], response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + "{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }", markdown: - "## mark_read\n\n`client.chats.markRead(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/read`\n\nMark a chat as read, optionally through a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark read through.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## retrieve\n\n`client.bridges.loginSessions.retrieve(bridgeID: string, loginSessionID: string): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; connection?: bridge_connection; currentStep?: object | object | object | object; error?: api_error; loginID?: string; }`\n\n**get** `/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}`\n\nGet the current state of a temporary bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginSessionID: string`\n Temporary bridge login session ID.\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; instructions?: string; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.retrieve('123', { bridgeID: 'local-whatsapp' });\n\nconsole.log(loginSession);\n```", perLanguage: { typescript: { - method: 'client.chats.markRead', + method: 'client.bridges.loginSessions.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst loginSession = await client.bridges.loginSessions.retrieve('123', {\n bridgeID: 'local-whatsapp',\n});\n\nconsole.log(loginSession.bridgeID);", }, python: { - method: 'chats.mark_read', + method: 'bridges.login_sessions.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.mark_read(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nlogin_session = client.bridges.login_sessions.retrieve(\n login_session_id="123",\n bridge_id="local-whatsapp",\n)\nprint(login_session.bridge_id)', }, go: { - method: 'client.Chats.MarkRead', + method: 'client.Bridges.LoginSessions.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkRead(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkReadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tloginSession, err := client.Bridges.LoginSessions.Get(\n\t\tcontext.TODO(),\n\t\t"123",\n\t\tbeeperdesktopapi.BridgeLoginSessionGetParams{\n\t\t\tBridgeID: "local-whatsapp",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", loginSession.BridgeID)\n}\n', }, cli: { - method: 'chats mark_read', + method: 'login_sessions retrieve', example: - "beeper-desktop-cli chats mark-read \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop bridges:login-sessions retrieve \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp \\\n --login-session-id 123", }, php: { - method: 'chats->markRead', + method: 'bridges->loginSessions->retrieve', example: - "chats->markRead(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($chat);", + "bridges->loginSessions->retrieve(\n '123', bridgeID: 'local-whatsapp'\n);\n\nvar_dump($loginSession);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/read \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/login-sessions/$LOGIN_SESSION_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'mark_unread', - endpoint: '/v1/chats/{chatID}/unread', - httpMethod: 'post', - summary: 'Mark a chat as unread', - description: 'Mark a chat as unread, optionally from a specific message ID.', - stainlessPath: '(resource) chats > (method) mark_unread', - qualified: 'client.chats.markUnread', - params: ['chatID: string;', 'messageID?: string;'], - response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", + name: 'cancel', + endpoint: '/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}', + httpMethod: 'delete', + summary: 'Cancel bridge login session', + description: 'Cancel a temporary bridge login session.', + stainlessPath: '(resource) bridges.login_sessions > (method) cancel', + qualified: 'client.bridges.loginSessions.cancel', + params: ['bridgeID: string;', 'loginSessionID: string;'], + response: "{ bridgeID: string; loginSessionID: string; status: 'cancelled'; }", markdown: - "## mark_unread\n\n`client.chats.markUnread(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/unread`\n\nMark a chat as unread, optionally from a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark unread from.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## cancel\n\n`client.bridges.loginSessions.cancel(bridgeID: string, loginSessionID: string): { bridgeID: string; loginSessionID: string; status: 'cancelled'; }`\n\n**delete** `/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}`\n\nCancel a temporary bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginSessionID: string`\n Temporary bridge login session ID.\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: 'cancelled'; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: 'cancelled'`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.bridges.loginSessions.cancel('123', { bridgeID: 'local-whatsapp' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.chats.markUnread', + method: 'client.bridges.loginSessions.cancel', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.bridges.loginSessions.cancel('123', { bridgeID: 'local-whatsapp' });\n\nconsole.log(response.bridgeID);", }, python: { - method: 'chats.mark_unread', + method: 'bridges.login_sessions.cancel', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.mark_unread(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.bridges.login_sessions.cancel(\n login_session_id="123",\n bridge_id="local-whatsapp",\n)\nprint(response.bridge_id)', }, go: { - method: 'client.Chats.MarkUnread', + method: 'client.Bridges.LoginSessions.Cancel', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkUnread(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkUnreadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Bridges.LoginSessions.Cancel(\n\t\tcontext.TODO(),\n\t\t"123",\n\t\tbeeperdesktopapi.BridgeLoginSessionCancelParams{\n\t\t\tBridgeID: "local-whatsapp",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.BridgeID)\n}\n', }, cli: { - method: 'chats mark_unread', + method: 'login_sessions cancel', example: - "beeper-desktop-cli chats mark-unread \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop bridges:login-sessions cancel \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp \\\n --login-session-id 123", }, php: { - method: 'chats->markUnread', + method: 'bridges->loginSessions->cancel', example: - "chats->markUnread(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($chat);", + "bridges->loginSessions->cancel(\n '123', bridgeID: 'local-whatsapp'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/unread \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/login-sessions/$LOGIN_SESSION_ID \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'notify_anyway', - endpoint: '/v1/chats/{chatID}/notify-anyway', + name: 'submit', + endpoint: '/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}/steps/{stepID}', httpMethod: '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.', - stainlessPath: '(resource) chats > (method) notify_anyway', - qualified: 'client.chats.notifyAnyway', - params: ['chatID: string;'], + summary: 'Submit bridge login step', + description: 'Submit input for the current step of a bridge login session.', + stainlessPath: '(resource) bridges.login_sessions.steps > (method) submit', + qualified: 'client.bridges.loginSessions.steps.submit', + params: [ + 'bridgeID: string;', + 'loginSessionID: string;', + 'stepID: string;', + "type: 'user_input' | 'cookies' | 'display_and_wait';", + 'fields?: object;', + 'lastURL?: string;', + "source?: 'api' | 'webview' | 'browser_extension';", + ], response: - "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", - markdown: - "## notify_anyway\n\n`client.chats.notifyAnyway(chatID: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/notify-anyway`\n\nForce a delivery notification when supported by the underlying network. Currently intended for iMessage on macOS; unsupported networks return an error.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", - perLanguage: { - typescript: { - method: 'client.chats.notifyAnyway', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", - }, - python: { - method: 'chats.notify_anyway', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.notify_anyway(\n "!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', - }, - go: { - method: 'client.Chats.NotifyAnyway', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.NotifyAnyway(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatNotifyAnywayParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', - }, - cli: { - method: 'chats notify_anyway', - example: - "beeper-desktop-cli chats notify-anyway \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, - php: { - method: 'chats->notifyAnyway', - example: - "chats->notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nvar_dump($chat);", - }, - http: { - example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/notify-anyway \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'create', - endpoint: '/v1/chats/{chatID}/reminders', - httpMethod: 'post', - summary: 'Create a chat reminder', - description: 'Set a reminder for a chat at a specific time', - stainlessPath: '(resource) chats.reminders > (method) create', - qualified: 'client.chats.reminders.create', - params: ['chatID: string;', 'reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; };'], + "{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }", markdown: - "## create\n\n`client.chats.reminders.create(chatID: string, reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }): void`\n\n**post** `/v1/chats/{chatID}/reminders`\n\nSet a reminder for a chat at a specific time\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }`\n Reminder configuration\n - `remindAt: string`\n Timestamp when the reminder should trigger.\n - `dismissOnIncomingMessage?: boolean`\n Cancel reminder if someone messages in the chat\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', { reminder: { remindAt: '2025-08-31T23:30:12.520Z' } })\n```", + "## submit\n\n`client.bridges.loginSessions.steps.submit(bridgeID: string, loginSessionID: string, stepID: string, type: 'user_input' | 'cookies' | 'display_and_wait', fields?: object, lastURL?: string, source?: 'api' | 'webview' | 'browser_extension'): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; connection?: bridge_connection; currentStep?: object | object | object | object; error?: api_error; loginID?: string; }`\n\n**post** `/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}/steps/{stepID}`\n\nSubmit input for the current step of a bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginSessionID: string`\n Temporary bridge login session ID.\n\n- `stepID: string`\n Bridge login step ID.\n\n- `type: 'user_input' | 'cookies' | 'display_and_wait'`\n\n- `fields?: object`\n\n- `lastURL?: string`\n\n- `source?: 'api' | 'webview' | 'browser_extension'`\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; instructions?: string; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.steps.submit('x', {\n bridgeID: 'local-whatsapp',\n loginSessionID: '123',\n type: 'user_input',\n});\n\nconsole.log(loginSession);\n```", perLanguage: { typescript: { - method: 'client.chats.reminders.create', + method: 'client.bridges.loginSessions.steps.submit', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', {\n reminder: { remindAt: '2025-08-31T23:30:12.520Z' },\n});", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst loginSession = await client.bridges.loginSessions.steps.submit('x', {\n bridgeID: 'local-whatsapp',\n loginSessionID: '123',\n type: 'user_input',\n});\n\nconsole.log(loginSession.bridgeID);", }, python: { - method: 'chats.reminders.create', + method: 'bridges.login_sessions.steps.submit', example: - 'import os\nfrom datetime import datetime\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.reminders.create(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n reminder={\n "remind_at": datetime.fromisoformat("2025-08-31T23:30:12.520")\n },\n)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nlogin_session = client.bridges.login_sessions.steps.submit(\n step_id="x",\n bridge_id="local-whatsapp",\n login_session_id="123",\n type="user_input",\n)\nprint(login_session.bridge_id)', }, go: { - method: 'client.Chats.Reminders.New', + method: 'client.Bridges.LoginSessions.Steps.Submit', example: - 'package main\n\nimport (\n\t"context"\n\t"time"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.New(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatReminderNewParams{\n\t\t\tReminder: beeperdesktopapi.ChatReminderNewParamsReminder{\n\t\t\t\tRemindAt: time.Now(),\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tloginSession, err := client.Bridges.LoginSessions.Steps.Submit(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.BridgeLoginSessionStepSubmitParams{\n\t\t\tBridgeID: "local-whatsapp",\n\t\t\tLoginSessionID: "123",\n\t\t\tType: beeperdesktopapi.BridgeLoginSessionStepSubmitParamsTypeUserInput,\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", loginSession.BridgeID)\n}\n', }, cli: { - method: 'reminders create', + method: 'steps submit', example: - "beeper-desktop-cli chats:reminders create \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --reminder \"{remindAt: '2025-08-31T23:30:12.520Z'}\"", + "beeper-desktop bridges:login-sessions:steps submit \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp \\\n --login-session-id 123 \\\n --step-id x \\\n --type user_input", }, php: { - method: 'chats->reminders->create', + method: 'bridges->loginSessions->steps->submit', example: - "chats->reminders->create(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reminder: [\n 'remindAt' => new \\DateTimeImmutable('2025-08-31T23:30:12.520Z'),\n 'dismissOnIncomingMessage' => true,\n ],\n);\n\nvar_dump($result);", + "bridges->loginSessions->steps->submit(\n 'x',\n bridgeID: 'local-whatsapp',\n loginSessionID: '123',\n type: 'user_input',\n fields: ['foo' => 'string'],\n lastURL: 'lastURL',\n source: 'api',\n);\n\nvar_dump($loginSession);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/reminders \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reminder": {\n "remindAt": "2025-08-31T23:30:12.520Z"\n }\n }\'', + 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/login-sessions/$LOGIN_SESSION_ID/steps/$STEP_ID \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "type": "user_input"\n }\'', }, }, }, { - name: 'delete', - endpoint: '/v1/chats/{chatID}/reminders', - httpMethod: 'delete', - summary: 'Delete a chat reminder', - description: 'Clear an existing reminder from a chat', - stainlessPath: '(resource) chats.reminders > (method) delete', - qualified: 'client.chats.reminders.delete', - params: ['chatID: string;'], + name: 'retrieve', + endpoint: '/v1/chats/{chatID}', + httpMethod: 'get', + summary: 'Retrieve chat details', + description: 'Retrieve chat details including metadata, participants, and latest message', + stainlessPath: '(resource) chats > (method) retrieve', + qualified: 'client.chats.retrieve', + params: ['chatID: string;', 'maxParticipantCount?: number;'], + response: + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## delete\n\n`client.chats.reminders.delete(chatID: string): void`\n\n**delete** `/v1/chats/{chatID}/reminders`\n\nClear an existing reminder from a chat\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", + "## retrieve\n\n`client.chats.retrieve(chatID: string, maxParticipantCount?: number): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/{chatID}`\n\nRetrieve chat details including metadata, participants, and latest message\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `maxParticipantCount?: number`\n 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.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.chats.reminders.delete', + method: 'client.chats.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com');", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'chats.reminders.delete', + method: 'chats.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.reminders.delete(\n "!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.retrieve(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.Chats.Reminders.Delete', + method: 'client.Chats.Get', example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.Delete(context.TODO(), "!NCdzlIaMjZUmvmvyHU:beeper.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Get(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatGetParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'reminders delete', + method: 'chats retrieve', example: - "beeper-desktop-cli chats:reminders delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", + "beeper-desktop chats retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'chats->reminders->delete', + method: 'chats->retrieve', example: - "chats->reminders->delete('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nvar_dump($result);", + "chats->retrieve(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', maxParticipantCount: 100\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/reminders \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'add', - endpoint: '/v1/chats/{chatID}/messages/{messageID}/reactions', + name: 'create', + endpoint: '/v1/chats', httpMethod: 'post', - summary: 'Add a reaction', - description: 'Add a reaction to an existing message.', - stainlessPath: '(resource) chats.messages.reactions > (method) add', - qualified: 'client.chats.messages.reactions.add', - params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;', 'transactionID?: string;'], + summary: 'Create a chat', + description: 'Create a direct or group chat from participant IDs. Returns the created chat.', + stainlessPath: '(resource) chats > (method) create', + qualified: 'client.chats.create', + params: [ + 'accountID: string;', + 'participantIDs: string[];', + "type: 'single' | 'group';", + 'messageText?: string;', + 'title?: string;', + ], response: - '{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }', - markdown: - "## add\n\n`client.chats.messages.reactions.add(chatID: string, messageID: string, reactionKey: string, transactionID?: string): { chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n**post** `/v1/chats/{chatID}/messages/{messageID}/reactions`\n\nAdd a reaction to an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to add (emoji, shortcode, or custom emoji key)\n\n- `transactionID?: string`\n Optional transaction ID for deduplication and send tracking\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n - `transactionID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.messages.reactions.add('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', reactionKey: 'x' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.chats.messages.reactions.add', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.chats.messages.reactions.add('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reactionKey: 'x',\n});\n\nconsole.log(response.chatID);", - }, - python: { - method: 'chats.messages.reactions.add', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.chats.messages.reactions.add(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n reaction_key="x",\n)\nprint(response.chat_id)', - }, - go: { - method: 'client.Chats.Messages.Reactions.Add', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Messages.Reactions.Add(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.ChatMessageReactionAddParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tReactionKey: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ChatID)\n}\n', - }, - cli: { - method: 'reactions add', - example: - "beeper-desktop-cli chats:messages:reactions add \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", - }, - php: { - method: 'chats->messages->reactions->add', - example: - "chats->messages->reactions->add(\n '1343993',\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reactionKey: 'x',\n transactionID: 'transactionID',\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID/reactions \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reactionKey": "x"\n }\'', - }, - }, - }, - { - name: 'delete', - endpoint: '/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}', - httpMethod: 'delete', - summary: 'Remove a reaction', - description: 'Remove the reaction added by the authenticated user from an existing message.', - stainlessPath: '(resource) chats.messages.reactions > (method) delete', - qualified: 'client.chats.messages.reactions.delete', - params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;'], - response: '{ chatID: string; messageID: string; reactionKey: string; success: true; }', + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## delete\n\n`client.chats.messages.reactions.delete(chatID: string, messageID: string, reactionKey: string): { chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}`\n\nRemove the reaction added by the authenticated user from an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to remove (emoji, shortcode, or custom emoji key)\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reaction = await client.chats.messages.reactions.delete('x', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993' });\n\nconsole.log(reaction);\n```", + "## create\n\n`client.chats.create(accountID: string, participantIDs: string[], type: 'single' | 'group', messageText?: string, title?: string): object`\n\n**post** `/v1/chats`\n\nCreate a direct or group chat from participant IDs. Returns the created chat.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `participantIDs: string[]`\n User IDs to include in the new chat.\n\n- `type: 'single' | 'group'`\n 'single' requires exactly one participantID; 'group' supports multiple participants and optional title.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n- `title?: string`\n Optional title for group chats; ignored for single chats on most networks.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.create({\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n});\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.chats.messages.reactions.delete', + method: 'client.chats.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reaction = await client.chats.messages.reactions.delete('x', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n messageID: '1343993',\n});\n\nconsole.log(reaction.chatID);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.create({\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n});\n\nconsole.log(chat);", }, python: { - method: 'chats.messages.reactions.delete', + method: 'chats.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreaction = client.chats.messages.reactions.delete(\n reaction_key="x",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n message_id="1343993",\n)\nprint(reaction.chat_id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.create(\n account_id="accountID",\n participant_ids=["string"],\n type="single",\n)\nprint(chat)', }, go: { - method: 'client.Chats.Messages.Reactions.Delete', + method: 'client.Chats.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treaction, err := client.Chats.Messages.Reactions.Delete(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.ChatMessageReactionDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tMessageID: "1343993",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reaction.ChatID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.New(context.TODO(), beeperdesktopapi.ChatNewParams{\n\t\tAccountID: "accountID",\n\t\tParticipantIDs: []string{"string"},\n\t\tType: beeperdesktopapi.ChatNewParamsTypeSingle,\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat)\n}\n', }, cli: { - method: 'reactions delete', + method: 'chats create', example: - "beeper-desktop-cli chats:messages:reactions delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", + "beeper-desktop chats create \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --participant-id string \\\n --type single", }, php: { - method: 'chats->messages->reactions->delete', + method: 'chats->create', example: - "chats->messages->reactions->delete(\n 'x', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($reaction);", + "chats->create(\n accountID: 'accountID',\n participantIDs: ['string'],\n type: 'single',\n messageText: 'messageText',\n title: 'title',\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID/reactions/$REACTION_KEY \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "accountID": "accountID",\n "participantIDs": [\n "string"\n ],\n "type": "single"\n }\'', }, }, }, { - name: 'search', - endpoint: '/v1/messages/search', - httpMethod: 'get', - summary: 'Search messages', - description: 'Search messages across chats.', - stainlessPath: '(resource) messages > (method) search', - qualified: 'client.messages.search', + name: 'start', + endpoint: '/v1/chats/start', + httpMethod: '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+.', + stainlessPath: '(resource) chats > (method) start', + qualified: 'client.chats.start', params: [ - 'accountIDs?: string[];', - 'chatIDs?: string[];', - "chatType?: 'group' | 'single';", - 'cursor?: string;', - 'dateAfter?: string;', - 'dateBefore?: string;', - "direction?: 'after' | 'before';", - 'excludeLowPriority?: boolean;', - 'includeMuted?: boolean;', - 'limit?: number;', - "mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[];", - 'query?: string;', - 'sender?: string;', + 'accountID: string;', + 'user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; };', + 'allowInvite?: boolean;', + 'messageText?: string;', ], response: - "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## search\n\n`client.messages.search(accountIDs?: string[], chatIDs?: string[], chatType?: 'group' | 'single', cursor?: string, dateAfter?: string, dateBefore?: string, direction?: 'after' | 'before', excludeLowPriority?: boolean, includeMuted?: boolean, limit?: number, mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[], query?: string, sender?: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/messages/search`\n\nSearch messages across chats.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit search to specific account IDs.\n\n- `chatIDs?: string[]`\n Limit search to specific chat IDs.\n\n- `chatType?: 'group' | 'single'`\n Filter by chat type: 'group' for group chats, 'single' for 1:1 chats.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `dateAfter?: string`\n Only include messages with timestamp strictly after this ISO 8601 datetime (e.g., '2024-07-01T00:00:00Z' or '2024-07-01T00:00:00+02:00').\n\n- `dateBefore?: string`\n Only include messages with timestamp strictly before this ISO 8601 datetime (e.g., '2024-07-31T23:59:59Z' or '2024-07-31T23:59:59+02:00').\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `excludeLowPriority?: boolean`\n Exclude messages marked Low Priority by the user. Default: true. Set to false to include all.\n\n- `includeMuted?: boolean`\n Include messages in 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.\n\n- `limit?: number`\n Maximum number of messages to return.\n\n- `mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[]`\n Filter messages by media types. Use ['any'] for any media type, or specify exact types like ['video', 'image']. Omit for no media filtering.\n\n- `query?: string`\n Literal word search (non-semantic). Finds messages containing these EXACT words in any order. Use single words users actually type, not concepts or phrases. Example: use \"dinner\" not \"dinner plans\", use \"sick\" not \"health issues\". If omitted, returns results filtered only by other parameters.\n\n- `sender?: string`\n Filter by sender: 'me' (messages sent by the authenticated user), 'others' (messages sent by others), or a specific user ID string (user.id).\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message);\n}\n```", + "## start\n\n`client.chats.start(accountID: string, user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }, allowInvite?: boolean, messageText?: string): object`\n\n**post** `/v1/chats/start`\n\nResolve 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+.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }`\n Merged user-like contact payload used to resolve the best identifier.\n - `id?: string`\n Known user ID when available.\n - `email?: string`\n Email candidate.\n - `fullName?: string`\n Display name hint used for ranking only.\n - `phoneNumber?: string`\n Phone number candidate (E.164 preferred).\n - `username?: string`\n Username/handle candidate.\n\n- `allowInvite?: boolean`\n Whether invite-based DM creation is allowed when required by the platform.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.messages.search', + method: 'client.chats.start', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message.id);\n}", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);", }, python: { - method: 'messages.search', + method: 'chats.start', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.messages.search()\npage = page.items[0]\nprint(page.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.chats.start(\n account_id="accountID",\n user={},\n)\nprint(response)', }, go: { - method: 'client.Messages.Search', + method: 'client.Chats.Start', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.Search(context.TODO(), beeperdesktopapi.MessageSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Start(context.TODO(), beeperdesktopapi.ChatStartParams{\n\t\tAccountID: "accountID",\n\t\tUser: beeperdesktopapi.ChatStartParamsUser{},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'messages search', - example: "beeper-desktop-cli messages search \\\n --access-token 'My Access Token'", + method: 'chats start', + example: + "beeper-desktop chats start \\\n --access-token 'My Access Token' \\\n --account-id accountID \\\n --user '{}'", }, php: { - method: 'messages->search', + method: 'chats->start', example: - "messages->search(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n chatIDs: ['!NCdzlIaMjZUmvmvyHU:beeper.com', '1231073'],\n chatType: 'group',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n dateAfter: new \\DateTimeImmutable('2025-08-01T00:00:00Z'),\n dateBefore: new \\DateTimeImmutable('2025-08-31T23:59:59Z'),\n direction: 'before',\n excludeLowPriority: true,\n includeMuted: true,\n limit: 20,\n mediaTypes: ['any'],\n query: 'dinner',\n sender: 'sender',\n);\n\nvar_dump($page);", + "chats->start(\n accountID: 'accountID',\n user: [\n 'id' => 'id',\n 'email' => 'email',\n 'fullName' => 'fullName',\n 'phoneNumber' => 'phoneNumber',\n 'username' => 'username',\n ],\n allowInvite: true,\n messageText: 'messageText',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/messages/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/start \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "accountID": "accountID",\n "user": {}\n }\'', }, - }, - }, - { - name: 'list', - endpoint: '/v1/chats/{chatID}/messages', - httpMethod: 'get', - summary: 'List messages', - description: 'List all messages in a chat with cursor-based pagination. Sorted by timestamp.', - stainlessPath: '(resource) messages > (method) list', - qualified: 'client.messages.list', - params: ['chatID: string;', 'cursor?: string;', "direction?: 'after' | 'before';"], - response: - "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", - markdown: - "## list\n\n`client.messages.list(chatID: string, cursor?: string, direction?: 'after' | 'before'): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages`\n\nList all messages in a chat with cursor-based pagination. Sorted by timestamp.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message);\n}\n```", - perLanguage: { - typescript: { - method: 'client.messages.list', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message.id);\n}", - }, - python: { - method: 'messages.list', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.messages.list(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\npage = page.items[0]\nprint(page.id)', - }, - go: { - method: 'client.Messages.List', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.List(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', - }, - cli: { - method: 'messages list', - example: - "beeper-desktop-cli messages list \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, - php: { - method: 'messages->list', - example: - "messages->list(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n);\n\nvar_dump($page);", - }, - http: { - example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'send', - endpoint: '/v1/chats/{chatID}/messages', - httpMethod: 'post', - summary: 'Send a message', - description: - 'Send a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.', - stainlessPath: '(resource) messages > (method) send', - qualified: 'client.messages.send', - params: [ - 'chatID: string;', - "attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; };", - 'replyToMessageID?: string;', - 'text?: string;', - ], - response: '{ chatID: string; pendingMessageID: string; }', - markdown: - "## send\n\n`client.messages.send(chatID: string, attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }, replyToMessageID?: string, text?: string): { chatID: string; pendingMessageID: string; }`\n\n**post** `/v1/chats/{chatID}/messages`\n\nSend a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }`\n Single attachment to send with the message\n - `uploadID: string`\n Upload ID from uploadAsset endpoint. Required to reference uploaded files.\n - `duration?: number`\n Duration in seconds (optional override of cached value)\n - `fileName?: string`\n Filename (optional override of cached value)\n - `mimeType?: string`\n MIME type (optional override of cached value)\n - `size?: { height: number; width: number; }`\n Dimensions (optional override of cached value)\n - `type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'`\n Attachment type hint (image, video, audio, file, gif, voice-note, sticker). If omitted, auto-detected from mimeType\n\n- `replyToMessageID?: string`\n Provide a message ID to send this as a reply to an existing message\n\n- `text?: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n\n### Returns\n\n- `{ chatID: string; pendingMessageID: string; }`\n\n - `chatID: string`\n - `pendingMessageID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.messages.send', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response.pendingMessageID);", - }, - python: { - method: 'messages.send', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.messages.send(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(response.pending_message_id)', - }, - go: { - method: 'client.Messages.Send', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Messages.Send(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageSendParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.PendingMessageID)\n}\n', - }, - cli: { - method: 'messages send', - example: - "beeper-desktop-cli messages send \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", - }, - php: { - method: 'messages->send', - example: - "messages->send(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n attachment: [\n 'uploadID' => 'uploadID',\n 'duration' => 0,\n 'fileName' => 'fileName',\n 'mimeType' => 'mimeType',\n 'size' => ['height' => 0, 'width' => 0],\n 'type' => 'image',\n ],\n replyToMessageID: 'replyToMessageID',\n text: 'text',\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'retrieve', - endpoint: '/v1/chats/{chatID}/messages/{messageID}', - httpMethod: 'get', - summary: 'Retrieve a message', - description: - 'Retrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.', - stainlessPath: '(resource) messages > (method) retrieve', - qualified: 'client.messages.retrieve', - params: ['chatID: string;', 'messageID: string;'], - response: - "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", - markdown: - "## retrieve\n\n`client.messages.retrieve(chatID: string, messageID: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages/{messageID}`\n\nRetrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.retrieve('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });\n\nconsole.log(message);\n```", - perLanguage: { - typescript: { - method: 'client.messages.retrieve', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst message = await client.messages.retrieve('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n});\n\nconsole.log(message.id);", - }, - python: { - method: 'messages.retrieve', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nmessage = client.messages.retrieve(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(message.id)', - }, - go: { - method: 'client.Messages.Get', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Get(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageGetParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message.ID)\n}\n', - }, - cli: { - method: 'messages retrieve', - example: - "beeper-desktop-cli messages retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", - }, - php: { - method: 'messages->retrieve', - example: - "messages->retrieve(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com'\n);\n\nvar_dump($message);", - }, - http: { - example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'update', - endpoint: '/v1/chats/{chatID}/messages/{messageID}', - httpMethod: 'put', - summary: 'Edit a message', - description: 'Edit the text content of an existing message. Messages with attachments cannot be edited.', - stainlessPath: '(resource) messages > (method) update', - qualified: 'client.messages.update', - params: ['chatID: string;', 'messageID: string;', 'text: string;'], - response: - "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", - markdown: - "## update\n\n`client.messages.update(chatID: string, messageID: string, text: string): object`\n\n**put** `/v1/chats/{chatID}/messages/{messageID}`\n\nEdit the text content of an existing message. Messages with attachments cannot be edited.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `text: string`\n New text content for the message\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.update('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x' });\n\nconsole.log(message);\n```", - perLanguage: { - typescript: { - method: 'client.messages.update', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst message = await client.messages.update('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n text: 'x',\n});\n\nconsole.log(message);", - }, - python: { - method: 'messages.update', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nmessage = client.messages.update(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n text="x",\n)\nprint(message)', - }, - go: { - method: 'client.Messages.Update', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Update(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageUpdateParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tText: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message)\n}\n', - }, - cli: { - method: 'messages update', - example: - "beeper-desktop-cli messages update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --text x", - }, - php: { - method: 'messages->update', - example: - "messages->update(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x'\n);\n\nvar_dump($message);", - }, - http: { - example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "text": "x"\n }\'', - }, - }, - }, - { - name: 'delete', - endpoint: '/v1/chats/{chatID}/messages/{messageID}', - httpMethod: 'delete', - summary: 'Delete a message', - description: - 'Delete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.', - stainlessPath: '(resource) messages > (method) delete', - qualified: 'client.messages.delete', - params: ['chatID: string;', 'messageID: string;', 'forEveryone?: boolean;'], - markdown: - "## delete\n\n`client.messages.delete(chatID: string, messageID: string, forEveryone?: boolean): void`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}`\n\nDelete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `forEveryone?: boolean`\n True to request deletion for everyone when the network supports it; false to delete only for the authenticated user when supported.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' })\n```", - perLanguage: { - typescript: { - method: 'client.messages.delete', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });", - }, - python: { - method: 'messages.delete', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.messages.delete(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', - }, - go: { - method: 'client.Messages.Delete', - example: - 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Messages.Delete(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', - }, - cli: { - method: 'messages delete', - example: - "beeper-desktop-cli messages delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", - }, - php: { - method: 'messages->delete', - example: - "messages->delete(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', forEveryone: true\n);\n\nvar_dump($result);", - }, - http: { - example: - 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'download', - endpoint: '/v1/assets/download', - httpMethod: '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.', - stainlessPath: '(resource) assets > (method) download', - qualified: 'client.assets.download', - params: ['url: string;'], - response: '{ error?: string; srcURL?: string; }', - markdown: - "## download\n\n`client.assets.download(url: string): { error?: string; srcURL?: string; }`\n\n**post** `/v1/assets/download`\n\nDownload a Matrix file using its mxc:// or localmxc:// URL to the device running Beeper Desktop and return the local file URL.\n\n### Parameters\n\n- `url: string`\n Matrix content URL (mxc:// or localmxc://) for the file to download.\n\n### Returns\n\n- `{ error?: string; srcURL?: string; }`\n\n - `error?: string`\n - `srcURL?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.assets.download', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response.error);", - }, - python: { - method: 'assets.download', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.download(\n url="mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n)\nprint(response.error)', - }, - go: { - method: 'client.Assets.Download', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Download(context.TODO(), beeperdesktopapi.AssetDownloadParams{\n\t\tURL: "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Error)\n}\n', - }, - cli: { - method: 'assets download', - example: - "beeper-desktop-cli assets download \\\n --access-token 'My Access Token' \\\n --url mxc://example.org/Q4x9CqGz1pB3Oa6XgJ", - }, - php: { - method: 'assets->download', - example: - "assets->download(\n url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ'\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/assets/download \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "url": "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ"\n }\'', - }, - }, - }, - { - name: 'upload', - endpoint: '/v1/assets/upload', - httpMethod: '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.', - stainlessPath: '(resource) assets > (method) upload', - qualified: 'client.assets.upload', - params: ['file: string;', 'fileName?: string;', 'mimeType?: string;'], - response: - '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', - markdown: - "## upload\n\n`client.assets.upload(file: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload`\n\nUpload 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.\n\n### Parameters\n\n- `file: string`\n The file to upload (max 500 MB).\n\n- `fileName?: string`\n Original filename. Defaults to the uploaded file name if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.assets.upload', - example: - "import fs from 'fs';\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response.width);", - }, - python: { - method: 'assets.upload', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.upload(\n file=b"Example data",\n)\nprint(response.width)', - }, - go: { - method: 'client.Assets.Upload', - example: - 'package main\n\nimport (\n\t"bytes"\n\t"context"\n\t"fmt"\n\t"io"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Upload(context.TODO(), beeperdesktopapi.AssetUploadParams{\n\t\tFile: io.Reader(bytes.NewBuffer([]byte("Example data"))),\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', - }, - cli: { - method: 'assets upload', - example: - "beeper-desktop-cli assets upload \\\n --access-token 'My Access Token' \\\n --file 'Example data'", - }, - php: { - method: 'assets->upload', - example: - "assets->upload(\n file: FileParam::fromString('Example data', filename: uniqid('file-upload-', true)),\n fileName: 'fileName',\n mimeType: 'mimeType',\n);\n\nvar_dump($response);", - }, - http: { - example: - "curl http://localhost:23373/v1/assets/upload \\\n -H 'Content-Type: multipart/form-data' \\\n -H \"Authorization: Bearer $BEEPER_ACCESS_TOKEN\" \\\n -F 'file=@/path/to/file'", - }, - }, - }, - { - name: 'upload_base64', - endpoint: '/v1/assets/upload/base64', - httpMethod: '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.', - stainlessPath: '(resource) assets > (method) upload_base64', - qualified: 'client.assets.uploadBase64', - params: ['content: string;', 'fileName?: string;', 'mimeType?: string;'], - response: - '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', - markdown: - "## upload_base64\n\n`client.assets.uploadBase64(content: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload/base64`\n\nUpload 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.\n\n### Parameters\n\n- `content: string`\n Base64-encoded file content (max ~500MB decoded)\n\n- `fileName?: string`\n Original filename. Generated if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.assets.uploadBase64', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response.width);", - }, - python: { - method: 'assets.upload_base64', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.upload_base64(\n content="x",\n)\nprint(response.width)', - }, - go: { - method: 'client.Assets.UploadBase64', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.UploadBase64(context.TODO(), beeperdesktopapi.AssetUploadBase64Params{\n\t\tContent: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', - }, - cli: { - method: 'assets upload_base64', - example: - "beeper-desktop-cli assets upload-base64 \\\n --access-token 'My Access Token' \\\n --content x", - }, - php: { - method: 'assets->uploadBase64', - example: - "assets->uploadBase64(\n content: 'x', fileName: 'fileName', mimeType: 'mimeType'\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/assets/upload/base64 \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "content": "x"\n }\'', - }, - }, - }, - { - name: 'serve', - endpoint: '/v1/assets/serve', - httpMethod: '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.', - stainlessPath: '(resource) assets > (method) serve', - qualified: 'client.assets.serve', - params: ['url: string;'], - response: 'string', - markdown: - "## serve\n\n`client.assets.serve(url: string): string`\n\n**get** `/v1/assets/serve`\n\nStream a file given an mxc://, localmxc://, or file:// URL. Downloads first if not cached. Supports Range requests for seeking in large files.\n\n### Parameters\n\n- `url: string`\n File URL to serve. Accepts mxc://, localmxc://, or file:// URLs.\n\n### Returns\n\n- `string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.serve({ url: 'x' });\n\nconsole.log(response);\n\nconst content = await response.blob()\nconsole.log(content)\n```", - perLanguage: { - typescript: { - method: 'client.assets.serve', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.serve({ url: 'x' });\n\nconsole.log(response);\n\nconst content = await response.blob();\nconsole.log(content);", - }, - python: { - method: 'assets.serve', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.serve(\n url="x",\n)\nprint(response)\ncontent = response.read()\nprint(content)', - }, - go: { - method: 'client.Assets.Serve', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Serve(context.TODO(), beeperdesktopapi.AssetServeParams{\n\t\tURL: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', - }, - cli: { - method: 'assets serve', - example: "beeper-desktop-cli assets serve \\\n --access-token 'My Access Token' \\\n --url x", - }, - php: { - method: 'assets->serve', - example: - "assets->serve(url: 'x');\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/assets/serve \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'retrieve', - endpoint: '/v1/info', - httpMethod: 'get', - summary: 'Retrieve server info', - description: - 'Returns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.', - stainlessPath: '(resource) info > (method) retrieve', - qualified: 'client.info.retrieve', - response: - '{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }', - markdown: - "## retrieve\n\n`client.info.retrieve(): { app: object; endpoints: object; platform: object; server: object; }`\n\n**get** `/v1/info`\n\nReturns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.\n\n### Returns\n\n- `{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }`\n\n - `app: { bundle_id: string; name: string; version: string; }`\n - `endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }`\n - `platform: { arch: string; os: string; release?: string; }`\n - `server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info);\n```", - perLanguage: { - typescript: { - method: 'client.info.retrieve', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info.app);", - }, - python: { - method: 'info.retrieve', - example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\ninfo = client.info.retrieve()\nprint(info.app)', - }, - go: { - method: 'client.Info.Get', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tinfo, err := client.Info.Get(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", info.App)\n}\n', - }, - cli: { - method: 'info retrieve', - example: "beeper-desktop-cli info retrieve \\\n --access-token 'My Access Token'", - }, - php: { - method: 'info->retrieve', - example: - "info->retrieve();\n\nvar_dump($info);", - }, - http: { - example: - 'curl http://localhost:23373/v1/info \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'status', - endpoint: '/v1/app/status', - httpMethod: 'get', - summary: 'Get app onboarding status', - description: - 'Return the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.', - stainlessPath: '(resource) app > (method) status', - qualified: 'client.app.status', - response: - "{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }", - markdown: - "## status\n\n`client.app.status(): { e2ee: object; state: string; matrix?: object; verification?: object; }`\n\n**get** `/v1/app/status`\n\nReturn the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.\n\n### Returns\n\n- `{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n - `e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }`\n - `state: string`\n - `matrix?: { deviceID: string; homeserver: string; userID: string; }`\n - `verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.status();\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.status', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.status();\n\nconsole.log(response.e2ee);", - }, - python: { - method: 'app.status', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.status()\nprint(response.e2ee)', - }, - go: { - method: 'client.App.Status', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Status(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.E2ee)\n}\n', - }, - cli: { - method: 'app status', - example: "beeper-desktop-cli app status \\\n --access-token 'My Access Token'", - }, - php: { - method: 'app->status', - example: - "app->status();\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/status \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'start', - endpoint: '/v1/app/login/start', - httpMethod: 'post', - summary: 'Start app login', - description: 'Start a first-party Beeper Desktop sign-in session.', - stainlessPath: '(resource) app.login > (method) start', - qualified: 'client.app.login.start', - response: '{ request: string; type: string[]; }', - markdown: - "## start\n\n`client.app.login.start(): { request: string; type: string[]; }`\n\n**post** `/v1/app/login/start`\n\nStart a first-party Beeper Desktop sign-in session.\n\n### Returns\n\n- `{ request: string; type: string[]; }`\n\n - `request: string`\n - `type: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.login.start', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response.request);", - }, - python: { - method: 'app.login.start', - example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.start()\nprint(response.request)', - }, - go: { - method: 'client.App.Login.Start', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Start(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Request)\n}\n', - }, - cli: { - method: 'login start', - example: "beeper-desktop-cli app:login start \\\n --access-token 'My Access Token'", - }, - php: { - method: 'app->login->start', - example: - "app->login->start();\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/login/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'email', - endpoint: '/v1/app/login/email', - httpMethod: 'post', - summary: 'Send login code', - description: 'Send a sign-in code to the user email address.', - stainlessPath: '(resource) app.login > (method) email', - qualified: 'client.app.login.email', - params: ['email: string;', 'request: string;'], - response: 'object', + }, + }, + { + name: 'list', + endpoint: '/v1/chats', + httpMethod: 'get', + summary: 'List chats', + description: + 'List all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.', + stainlessPath: '(resource) chats > (method) list', + qualified: 'client.chats.list', + params: ['accountIDs?: string[];', 'cursor?: string;', "direction?: 'after' | 'before';"], + response: + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## email\n\n`client.app.login.email(email: string, request: string): object`\n\n**post** `/v1/app/login/email`\n\nSend a sign-in code to the user email address.\n\n### Parameters\n\n- `email: string`\n Email address to send the sign-in code to.\n\n- `request: string`\n Login request ID returned by the start step.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);\n```", + "## list\n\n`client.chats.list(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before'): object`\n\n**get** `/v1/chats`\n\nList all chats sorted by last activity (most recent first). Combines all accounts into a single paginated list.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit to specific account IDs. If omitted, fetches from all accounts.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n Chat with optional last message preview.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chatListResponse of client.chats.list()) {\n console.log(chatListResponse);\n}\n```", perLanguage: { typescript: { - method: 'client.app.login.email', + method: 'client.chats.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const chatListResponse of client.chats.list()) {\n console.log(chatListResponse);\n}", }, python: { - method: 'app.login.email', + method: 'chats.list', example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.email(\n email="dev@stainless.com",\n request="request",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.chats.list()\npage = page.items[0]\nprint(page)', }, go: { - method: 'client.App.Login.Email', + method: 'client.Chats.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Email(context.TODO(), beeperdesktopapi.AppLoginEmailParams{\n\t\tEmail: "dev@stainless.com",\n\t\tRequest: "request",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.List(context.TODO(), beeperdesktopapi.ChatListParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'login email', - example: - "beeper-desktop-cli app:login email \\\n --access-token 'My Access Token' \\\n --email dev@stainless.com \\\n --request request", + method: 'chats list', + example: "beeper-desktop chats list \\\n --access-token 'My Access Token'", }, php: { - method: 'app->login->email', + method: 'chats->list', example: - "app->login->email(\n email: 'dev@stainless.com', request: 'request'\n);\n\nvar_dump($response);", + "chats->list(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/app/login/email \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "email": "dev@stainless.com",\n "request": "request"\n }\'', + 'curl http://localhost:23373/v1/chats \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'response', - endpoint: '/v1/app/login/response', - httpMethod: 'post', - summary: 'Complete login with code', - description: - 'Finish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.', - stainlessPath: '(resource) app.login > (method) response', - qualified: 'client.app.login.response', - params: ['request: string;', 'response: string;'], + name: 'search', + endpoint: '/v1/chats/search', + httpMethod: 'get', + summary: 'Search chats', + description: 'Search chats by title, network, or participant names.', + stainlessPath: '(resource) chats > (method) search', + qualified: 'client.chats.search', + params: [ + 'accountIDs?: string[];', + 'cursor?: string;', + "direction?: 'after' | 'before';", + "inbox?: 'primary' | 'low-priority' | 'archive';", + 'includeMuted?: boolean;', + 'lastActivityAfter?: string;', + 'lastActivityBefore?: string;', + 'limit?: number;', + 'query?: string;', + "scope?: 'titles' | 'participants';", + "type?: 'single' | 'group' | 'any';", + 'unreadOnly?: boolean;', + ], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## response\n\n`client.app.login.response(request: string, response: string): { appState: object; desktopAPI: object; matrix: object; } | { copy: object; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n**post** `/v1/app/login/response`\n\nFinish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.\n\n### Parameters\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `response: string`\n Sign-in code from the user email.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);\n```", + "## search\n\n`client.chats.search(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before', inbox?: 'primary' | 'low-priority' | 'archive', includeMuted?: boolean, lastActivityAfter?: string, lastActivityBefore?: string, limit?: number, query?: string, scope?: 'titles' | 'participants', type?: 'single' | 'group' | 'any', unreadOnly?: boolean): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/search`\n\nSearch chats by title, network, or participant names.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Provide an array of account IDs to filter chats from specific messaging accounts only\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `inbox?: 'primary' | 'low-priority' | 'archive'`\n Filter by inbox type: \"primary\" (non-archived, non-low-priority), \"low-priority\", or \"archive\". If not specified, shows all chats.\n\n- `includeMuted?: boolean`\n 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.\n\n- `lastActivityAfter?: string`\n Provide an ISO datetime string to only retrieve chats with last activity after this time\n\n- `lastActivityBefore?: string`\n Provide an ISO datetime string to only retrieve chats with last activity before this time\n\n- `limit?: number`\n Set the maximum number of chats to retrieve. Valid range: 1-200, default is 50\n\n- `query?: string`\n Literal token search (non-semantic). Use single words users type (e.g., \"dinner\"). When multiple words provided, ALL must match. Case-insensitive.\n\n- `scope?: 'titles' | 'participants'`\n Search scope: 'titles' matches title + network; 'participants' matches participant names.\n\n- `type?: 'single' | 'group' | 'any'`\n Specify the type of chats to retrieve: use \"single\" for direct messages, \"group\" for group chats, or \"any\" to get all types\n\n- `unreadOnly?: boolean`\n Set to true to only retrieve chats that have unread messages\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat);\n}\n```", perLanguage: { typescript: { - method: 'client.app.login.response', + method: 'client.chats.search', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat.id);\n}", }, python: { - method: 'app.login.response', + method: 'chats.search', example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.response(\n request="request",\n response="response",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.chats.search()\npage = page.items[0]\nprint(page.id)', }, go: { - method: 'client.App.Login.Response', + method: 'client.Chats.Search', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Response(context.TODO(), beeperdesktopapi.AppLoginResponseParams{\n\t\tRequest: "request",\n\t\tResponse: "response",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Chats.Search(context.TODO(), beeperdesktopapi.ChatSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'login response', - example: - "beeper-desktop-cli app:login response \\\n --access-token 'My Access Token' \\\n --request request \\\n --response response", + method: 'chats search', + example: "beeper-desktop chats search \\\n --access-token 'My Access Token'", }, php: { - method: 'app->login->response', + method: 'chats->search', example: - "app->login->response(\n request: 'request', response: 'response'\n);\n\nvar_dump($response);", + "chats->search(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n inbox: 'primary',\n includeMuted: true,\n lastActivityAfter: new \\DateTimeImmutable('2019-12-27T18:11:19.117Z'),\n lastActivityBefore: new \\DateTimeImmutable('2019-12-27T18:11:19.117Z'),\n limit: 1,\n query: 'x',\n scope: 'titles',\n type: 'single',\n unreadOnly: true,\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/app/login/response \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "request": "request",\n "response": "response"\n }\'', + 'curl http://localhost:23373/v1/chats/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'register', - endpoint: '/v1/app/login/register', + name: 'archive', + endpoint: '/v1/chats/{chatID}/archive', httpMethod: 'post', - summary: 'Create account', - description: 'Create a Beeper account after the user chooses a username and accepts the Terms of Use.', - stainlessPath: '(resource) app.login > (method) register', - qualified: 'client.app.login.register', - params: ['acceptTerms: true;', 'leadToken: string;', 'request: string;', 'username: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; }", + 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', + stainlessPath: '(resource) chats > (method) archive', + qualified: 'client.chats.archive', + params: ['chatID: string;', 'archived?: boolean;'], markdown: - "## register\n\n`client.app.login.register(acceptTerms: true, leadToken: string, request: string, username: string): { appState: object; desktopAPI: object; matrix: object; }`\n\n**post** `/v1/app/login/register`\n\nCreate a Beeper account after the user chooses a username and accepts the Terms of Use.\n\n### Parameters\n\n- `acceptTerms: true`\n Confirms that the user accepted the Terms of Use and acknowledged the Privacy Policy.\n\n- `leadToken: string`\n Registration token returned by Beeper.\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `username: string`\n Username selected by the user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }`\n - `matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response);\n```", + "## archive\n\n`client.chats.archive(chatID: string, archived?: boolean): void`\n\n**post** `/v1/chats/{chatID}/archive`\n\nArchive or unarchive a chat. Set archived=true to move to archive, archived=false to move back to inbox\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `archived?: boolean`\n True to archive, false to unarchive\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", perLanguage: { typescript: { - method: 'client.app.login.register', + method: 'client.chats.archive', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com');", }, python: { - method: 'app.login.register', + method: 'chats.archive', example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.register(\n accept_terms=True,\n lead_token="leadToken",\n request="request",\n username="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.archive(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', }, go: { - method: 'client.App.Login.Register', + method: 'client.Chats.Archive', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Register(context.TODO(), beeperdesktopapi.AppLoginRegisterParams{\n\t\tAcceptTerms: true,\n\t\tLeadToken: "leadToken",\n\t\tRequest: "request",\n\t\tUsername: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Archive(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatArchiveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, cli: { - method: 'login register', + method: 'chats archive', example: - "beeper-desktop-cli app:login register \\\n --access-token 'My Access Token' \\\n --accept-terms true \\\n --lead-token leadToken \\\n --request request \\\n --username x", + "beeper-desktop chats archive \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->login->register', + method: 'chats->archive', example: - "app->login->register(\n acceptTerms: true, leadToken: 'leadToken', request: 'request', username: 'x'\n);\n\nvar_dump($response);", + "chats->archive(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', archived: true\n);\n\nvar_dump($result);", }, http: { example: - 'curl http://localhost:23373/v1/app/login/register \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "acceptTerms": true,\n "leadToken": "leadToken",\n "request": "request",\n "username": "x"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/archive \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'verify', - endpoint: '/v1/app/e2ee/recovery-code/verify', - httpMethod: 'post', - summary: 'Verify with recovery key', - description: 'Unlock encrypted messages with the user recovery key.', - stainlessPath: '(resource) app.e2ee.recovery_code > (method) verify', - qualified: 'client.app.e2ee.recoveryCode.verify', - params: ['recoveryCode: string;'], + name: 'update', + endpoint: '/v1/chats/{chatID}', + httpMethod: '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.', + stainlessPath: '(resource) chats > (method) update', + qualified: 'client.chats.update', + params: [ + 'chatID: string;', + 'description?: string;', + 'draft?: { text: string; attachments?: object; };', + 'imgURL?: string;', + 'isArchived?: boolean;', + 'isLowPriority?: boolean;', + 'isMuted?: boolean;', + 'isPinned?: boolean;', + 'messageExpirySeconds?: number;', + 'title?: string;', + ], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## verify\n\n`client.app.e2ee.recoveryCode.verify(recoveryCode: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/verify`\n\nUnlock encrypted messages with the user recovery key.\n\n### Parameters\n\n- `recoveryCode: string`\n Recovery key saved by the user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' });\n\nconsole.log(response);\n```", + "## update\n\n`client.chats.update(chatID: string, description?: string, draft?: { text: string; attachments?: object; }, imgURL?: string, isArchived?: boolean, isLowPriority?: boolean, isMuted?: boolean, isPinned?: boolean, messageExpirySeconds?: number, title?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**patch** `/v1/chats/{chatID}`\n\nUpdate 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.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `description?: string`\n Group chat description/topic. Support depends on the chat account and chat permissions.\n\n- `draft?: { text: string; attachments?: object; }`\n Draft object to set or clear. Non-empty drafts are only accepted when the current draft is empty. Send draft=null to clear text and attachments together before setting a new draft.\n - `text: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n - `attachments?: object`\n Draft attachments keyed by attachment ID. Each attachment must reference an uploadID returned by the upload file endpoint.\n\n- `imgURL?: string`\n Local filesystem path to a group chat avatar image. Support depends on the chat account and chat permissions.\n\n- `isArchived?: boolean`\n Archive or unarchive the chat.\n\n- `isLowPriority?: boolean`\n Mark or unmark the chat as low priority when supported by the account.\n\n- `isMuted?: boolean`\n Mute or unmute the chat.\n\n- `isPinned?: boolean`\n Pin or unpin the chat when supported by the account.\n\n- `messageExpirySeconds?: number`\n Disappearing-message timer in seconds, or null to clear when supported.\n\n- `title?: string`\n Custom chat title. Support depends on the chat account and chat permissions.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.recoveryCode.verify', + method: 'client.chats.update', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' });\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.e2ee.recovery_code.verify', + method: 'chats.update', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.verify(\n recovery_code="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.update(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.E2ee.RecoveryCode.Verify', + method: 'client.Chats.Update', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.Verify(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeVerifyParams{\n\t\tRecoveryCode: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.Update(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatUpdateParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'recovery_code verify', + method: 'chats update', example: - "beeper-desktop-cli app:e2ee:recovery-code verify \\\n --access-token 'My Access Token' \\\n --recovery-code x", + "beeper-desktop chats update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->recoveryCode->verify', + method: 'chats->update', example: - "app->e2ee->recoveryCode->verify(recoveryCode: 'x');\n\nvar_dump($response);", + "chats->update(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n description: 'description',\n draft: [\n 'text' => 'text',\n 'attachments' => [\n 'foo' => [\n 'uploadID' => 'uploadID',\n 'id' => 'id',\n 'duration' => 0,\n 'fileName' => 'fileName',\n 'mimeType' => 'mimeType',\n 'size' => ['height' => 0, 'width' => 0],\n 'type' => 'image',\n ],\n ],\n ],\n imgURL: 'imgURL',\n isArchived: true,\n isLowPriority: true,\n isMuted: true,\n isPinned: true,\n messageExpirySeconds: 0,\n title: 'title',\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/recovery-code/verify \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryCode": "x"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID \\\n -X PATCH \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'mark_backed_up', - endpoint: '/v1/app/e2ee/recovery-code/mark-backed-up', + name: 'mark_read', + endpoint: '/v1/chats/{chatID}/read', httpMethod: 'post', - summary: 'Mark recovery key as saved', - description: 'Record that the user saved their recovery key.', - stainlessPath: '(resource) app.e2ee.recovery_code > (method) mark_backed_up', - qualified: 'client.app.e2ee.recoveryCode.markBackedUp', + summary: 'Mark a chat as read', + description: 'Mark a chat as read, optionally through a specific message ID.', + stainlessPath: '(resource) chats > (method) mark_read', + qualified: 'client.chats.markRead', + params: ['chatID: string;', 'messageID?: string;'], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## mark_backed_up\n\n`client.app.e2ee.recoveryCode.markBackedUp(): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/mark-backed-up`\n\nRecord that the user saved their recovery key.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.markBackedUp();\n\nconsole.log(response);\n```", + "## mark_read\n\n`client.chats.markRead(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/read`\n\nMark a chat as read, optionally through a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark read through.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.recoveryCode.markBackedUp', + method: 'client.chats.markRead', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.markBackedUp();\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.e2ee.recovery_code.mark_backed_up', + method: 'chats.mark_read', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.mark_backed_up()\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.mark_read(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.E2ee.RecoveryCode.MarkBackedUp', + method: 'client.Chats.MarkRead', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.MarkBackedUp(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkRead(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkReadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'recovery_code mark_backed_up', + method: 'chats mark_read', example: - "beeper-desktop-cli app:e2ee:recovery-code mark-backed-up \\\n --access-token 'My Access Token'", + "beeper-desktop chats mark-read \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->recoveryCode->markBackedUp', + method: 'chats->markRead', example: - "app->e2ee->recoveryCode->markBackedUp();\n\nvar_dump($response);", + "chats->markRead(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/recovery-code/mark-backed-up \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/read \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'create', - endpoint: '/v1/app/e2ee/recovery-code/reset', + name: 'mark_unread', + endpoint: '/v1/chats/{chatID}/unread', httpMethod: 'post', - summary: 'Create new recovery key', - description: 'Create a new recovery key when the user cannot use the existing one.', - stainlessPath: '(resource) app.e2ee.recovery_code.reset > (method) create', - qualified: 'client.app.e2ee.recoveryCode.reset.create', - params: ['recoveryCode?: string;'], + summary: 'Mark a chat as unread', + description: 'Mark a chat as unread, optionally from a specific message ID.', + stainlessPath: '(resource) chats > (method) mark_unread', + qualified: 'client.chats.markUnread', + params: ['chatID: string;', 'messageID?: string;'], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; recoveryCode: string; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## create\n\n`client.app.e2ee.recoveryCode.reset.create(recoveryCode?: string): { appState: object; recoveryCode: string; }`\n\n**post** `/v1/app/e2ee/recovery-code/reset`\n\nCreate a new recovery key when the user cannot use the existing one.\n\n### Parameters\n\n- `recoveryCode?: string`\n Existing recovery key, if the user has it.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; recoveryCode: string; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `recoveryCode: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reset = await client.app.e2ee.recoveryCode.reset.create();\n\nconsole.log(reset);\n```", + "## mark_unread\n\n`client.chats.markUnread(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/unread`\n\nMark a chat as unread, optionally from a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark unread from.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.recoveryCode.reset.create', + method: 'client.chats.markUnread', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reset = await client.app.e2ee.recoveryCode.reset.create();\n\nconsole.log(reset.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.e2ee.recovery_code.reset.create', + method: 'chats.mark_unread', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreset = client.app.e2ee.recovery_code.reset.create()\nprint(reset.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.mark_unread(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.E2ee.RecoveryCode.Reset.New', + method: 'client.Chats.MarkUnread', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treset, err := client.App.E2ee.RecoveryCode.Reset.New(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeResetNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reset.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.MarkUnread(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatMarkUnreadParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'reset create', + method: 'chats mark_unread', example: - "beeper-desktop-cli app:e2ee:recovery-code:reset create \\\n --access-token 'My Access Token'", + "beeper-desktop chats mark-unread \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->recoveryCode->reset->create', + method: 'chats->markUnread', example: - "app->e2ee->recoveryCode->reset->create(\n recoveryCode: 'recoveryCode'\n);\n\nvar_dump($reset);", + "chats->markUnread(\n '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/recovery-code/reset \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/unread \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'confirm', - endpoint: '/v1/app/e2ee/recovery-code/reset/confirm', + name: 'notify_anyway', + endpoint: '/v1/chats/{chatID}/notify-anyway', httpMethod: 'post', - summary: 'Confirm new recovery key', - description: 'Confirm that the new recovery key should be used for this account.', - stainlessPath: '(resource) app.e2ee.recovery_code.reset > (method) confirm', - qualified: 'client.app.e2ee.recoveryCode.reset.confirm', - params: ['recoveryCode: string;'], + 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.', + stainlessPath: '(resource) chats > (method) notify_anyway', + qualified: 'client.chats.notifyAnyway', + params: ['chatID: string;'], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## confirm\n\n`client.app.e2ee.recoveryCode.reset.confirm(recoveryCode: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/recovery-code/reset/confirm`\n\nConfirm that the new recovery key should be used for this account.\n\n### Parameters\n\n- `recoveryCode: string`\n New recovery key returned by the reset step.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' });\n\nconsole.log(response);\n```", + "## notify_anyway\n\n`client.chats.notifyAnyway(chatID: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/notify-anyway`\n\nForce a delivery notification when supported by the underlying network. Currently intended for iMessage on macOS; unsupported networks return an error.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.recoveryCode.reset.confirm', + method: 'client.chats.notifyAnyway', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' });\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat.id);", }, python: { - method: 'app.e2ee.recovery_code.reset.confirm', + method: 'chats.notify_anyway', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.recovery_code.reset.confirm(\n recovery_code="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nchat = client.chats.notify_anyway(\n "!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(chat.id)', }, go: { - method: 'client.App.E2ee.RecoveryCode.Reset.Confirm', + method: 'client.Chats.NotifyAnyway', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.RecoveryCode.Reset.Confirm(context.TODO(), beeperdesktopapi.AppE2eeRecoveryCodeResetConfirmParams{\n\t\tRecoveryCode: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tchat, err := client.Chats.NotifyAnyway(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatNotifyAnywayParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", chat.ID)\n}\n', }, cli: { - method: 'reset confirm', + method: 'chats notify_anyway', example: - "beeper-desktop-cli app:e2ee:recovery-code:reset confirm \\\n --access-token 'My Access Token' \\\n --recovery-code x", + "beeper-desktop chats notify-anyway \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->recoveryCode->reset->confirm', + method: 'chats->notifyAnyway', example: - "app->e2ee->recoveryCode->reset->confirm(recoveryCode: 'x');\n\nvar_dump($response);", + "chats->notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nvar_dump($chat);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/recovery-code/reset/confirm \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryCode": "x"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/notify-anyway \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { name: 'create', - endpoint: '/v1/app/e2ee/verification', + endpoint: '/v1/chats/{chatID}/reminders', httpMethod: 'post', - summary: 'Start device verification', - description: 'Start verifying this device from another signed-in device.', - stainlessPath: '(resource) app.e2ee.verification > (method) create', - qualified: 'client.app.e2ee.verification.create', - params: ['userID?: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; verificationID: string; }", + summary: 'Create a chat reminder', + description: 'Set a reminder for a chat at a specific time', + stainlessPath: '(resource) chats.reminders > (method) create', + qualified: 'client.chats.reminders.create', + params: ['chatID: string;', 'reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; };'], markdown: - "## create\n\n`client.app.e2ee.verification.create(userID?: string): { appState: object; verificationID: string; }`\n\n**post** `/v1/app/e2ee/verification`\n\nStart verifying this device from another signed-in device.\n\n### Parameters\n\n- `userID?: string`\n User ID to verify. Defaults to the signed-in user.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; verificationID: string; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n - `verificationID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.e2ee.verification.create();\n\nconsole.log(verification);\n```", + "## create\n\n`client.chats.reminders.create(chatID: string, reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }): void`\n\n**post** `/v1/chats/{chatID}/reminders`\n\nSet a reminder for a chat at a specific time\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }`\n Reminder configuration\n - `remindAt: string`\n Timestamp when the reminder should trigger.\n - `dismissOnIncomingMessage?: boolean`\n Cancel reminder if someone messages in the chat\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', { reminder: { remindAt: '2025-08-31T23:30:12.520Z' } })\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.create', + method: 'client.chats.reminders.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.e2ee.verification.create();\n\nconsole.log(verification.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', {\n reminder: { remindAt: '2025-08-31T23:30:12.520Z' },\n});", }, python: { - method: 'app.e2ee.verification.create', + method: 'chats.reminders.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.e2ee.verification.create()\nprint(verification.app_state)', + 'import os\nfrom datetime import datetime\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.reminders.create(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n reminder={\n "remind_at": datetime.fromisoformat("2025-08-31T23:30:12.520")\n },\n)', }, go: { - method: 'client.App.E2ee.Verification.New', + method: 'client.Chats.Reminders.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.E2ee.Verification.New(context.TODO(), beeperdesktopapi.AppE2eeVerificationNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"time"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.New(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.ChatReminderNewParams{\n\t\t\tReminder: beeperdesktopapi.ChatReminderNewParamsReminder{\n\t\t\t\tRemindAt: time.Now(),\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, cli: { - method: 'verification create', - example: "beeper-desktop-cli app:e2ee:verification create \\\n --access-token 'My Access Token'", + method: 'reminders create', + example: + "beeper-desktop chats:reminders create \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --reminder \"{remindAt: '2025-08-31T23:30:12.520Z'}\"", }, php: { - method: 'app->e2ee->verification->create', + method: 'chats->reminders->create', example: - "app->e2ee->verification->create(userID: 'userID');\n\nvar_dump($verification);", + "chats->reminders->create(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reminder: [\n 'remindAt' => new \\DateTimeImmutable('2025-08-31T23:30:12.520Z'),\n 'dismissOnIncomingMessage' => true,\n ],\n);\n\nvar_dump($result);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/reminders \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reminder": {\n "remindAt": "2025-08-31T23:30:12.520Z"\n }\n }\'', }, }, }, { - name: 'accept', - endpoint: '/v1/app/e2ee/verification/{verificationID}/accept', - httpMethod: 'post', - summary: 'Accept device verification', - description: 'Accept an incoming device verification request.', - stainlessPath: '(resource) app.e2ee.verification > (method) accept', - qualified: 'client.app.e2ee.verification.accept', - params: ['verificationID: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + name: 'delete', + endpoint: '/v1/chats/{chatID}/reminders', + httpMethod: 'delete', + summary: 'Delete a chat reminder', + description: 'Clear an existing reminder from a chat', + stainlessPath: '(resource) chats.reminders > (method) delete', + qualified: 'client.chats.reminders.delete', + params: ['chatID: string;'], markdown: - "## accept\n\n`client.app.e2ee.verification.accept(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/accept`\n\nAccept an incoming device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.accept('x');\n\nconsole.log(response);\n```", + "## delete\n\n`client.chats.reminders.delete(chatID: string): void`\n\n**delete** `/v1/chats/{chatID}/reminders`\n\nClear an existing reminder from a chat\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.accept', + method: 'client.chats.reminders.delete', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.accept('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com');", }, python: { - method: 'app.e2ee.verification.accept', + method: 'chats.reminders.delete', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.accept(\n "x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.chats.reminders.delete(\n "!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', }, go: { - method: 'client.App.E2ee.Verification.Accept', + method: 'client.Chats.Reminders.Delete', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Accept(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Chats.Reminders.Delete(context.TODO(), "!NCdzlIaMjZUmvmvyHU:beeper.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, cli: { - method: 'verification accept', + method: 'reminders delete', example: - "beeper-desktop-cli app:e2ee:verification accept \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop chats:reminders delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->accept', + method: 'chats->reminders->delete', example: - "app->e2ee->verification->accept('x');\n\nvar_dump($response);", + "chats->reminders->delete('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nvar_dump($result);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/accept \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/reminders \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'cancel', - endpoint: '/v1/app/e2ee/verification/{verificationID}/cancel', + name: 'add', + endpoint: '/v1/chats/{chatID}/messages/{messageID}/reactions', httpMethod: 'post', - summary: 'Cancel device verification', - description: 'Cancel an active device verification request.', - stainlessPath: '(resource) app.e2ee.verification > (method) cancel', - qualified: 'client.app.e2ee.verification.cancel', - params: ['verificationID: string;', 'code?: string;', 'reason?: string;'], + summary: 'Add a reaction', + description: 'Add a reaction to an existing message.', + stainlessPath: '(resource) chats.messages.reactions > (method) add', + qualified: 'client.chats.messages.reactions.add', + params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;', 'transactionID?: string;'], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + '{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }', markdown: - "## cancel\n\n`client.app.e2ee.verification.cancel(verificationID: string, code?: string, reason?: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/cancel`\n\nCancel an active device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n- `code?: string`\n Optional cancellation code.\n\n- `reason?: string`\n Optional user-facing cancellation reason.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.cancel('x');\n\nconsole.log(response);\n```", + "## add\n\n`client.chats.messages.reactions.add(chatID: string, messageID: string, reactionKey: string, transactionID?: string): { chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n**post** `/v1/chats/{chatID}/messages/{messageID}/reactions`\n\nAdd a reaction to an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to add (emoji, shortcode, or custom emoji key)\n\n- `transactionID?: string`\n Optional transaction ID for deduplication and send tracking\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n - `transactionID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.messages.reactions.add('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', reactionKey: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.cancel', + method: 'client.chats.messages.reactions.add', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.cancel('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.chats.messages.reactions.add('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reactionKey: 'x',\n});\n\nconsole.log(response.chatID);", }, python: { - method: 'app.e2ee.verification.cancel', + method: 'chats.messages.reactions.add', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.cancel(\n verification_id="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.chats.messages.reactions.add(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n reaction_key="x",\n)\nprint(response.chat_id)', }, go: { - method: 'client.App.E2ee.Verification.Cancel', + method: 'client.Chats.Messages.Reactions.Add', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Cancel(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.AppE2eeVerificationCancelParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Chats.Messages.Reactions.Add(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.ChatMessageReactionAddParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tReactionKey: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ChatID)\n}\n', }, cli: { - method: 'verification cancel', + method: 'reactions add', example: - "beeper-desktop-cli app:e2ee:verification cancel \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop chats:messages:reactions add \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", }, php: { - method: 'app->e2ee->verification->cancel', + method: 'chats->messages->reactions->add', example: - "app->e2ee->verification->cancel(\n 'x', code: 'code', reason: 'reason'\n);\n\nvar_dump($response);", + "chats->messages->reactions->add(\n '1343993',\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n reactionKey: 'x',\n transactionID: 'transactionID',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/cancel \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID/reactions \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reactionKey": "x"\n }\'', }, }, }, { - name: 'scan', - endpoint: '/v1/app/e2ee/verification/qr/scan', - httpMethod: 'post', - summary: 'Scan verification QR code', - description: 'Submit the QR code scanned from another signed-in device.', - stainlessPath: '(resource) app.e2ee.verification.qr > (method) scan', - qualified: 'client.app.e2ee.verification.qr.scan', - params: ['data: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + name: 'delete', + endpoint: '/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}', + httpMethod: 'delete', + summary: 'Remove a reaction', + description: 'Remove the reaction added by the authenticated user from an existing message.', + stainlessPath: '(resource) chats.messages.reactions > (method) delete', + qualified: 'client.chats.messages.reactions.delete', + params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;'], + response: '{ chatID: string; messageID: string; reactionKey: string; success: true; }', markdown: - "## scan\n\n`client.app.e2ee.verification.qr.scan(data: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/qr/scan`\n\nSubmit the QR code scanned from another signed-in device.\n\n### Parameters\n\n- `data: string`\n QR code payload scanned from the other device.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.qr.scan({ data: 'x' });\n\nconsole.log(response);\n```", + "## delete\n\n`client.chats.messages.reactions.delete(chatID: string, messageID: string, reactionKey: string): { chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}`\n\nRemove the reaction added by the authenticated user from an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to remove (emoji, shortcode, or custom emoji key)\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reaction = await client.chats.messages.reactions.delete('x', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993' });\n\nconsole.log(reaction);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.qr.scan', + method: 'client.chats.messages.reactions.delete', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.qr.scan({ data: 'x' });\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reaction = await client.chats.messages.reactions.delete('x', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n messageID: '1343993',\n});\n\nconsole.log(reaction.chatID);", }, python: { - method: 'app.e2ee.verification.qr.scan', + method: 'chats.messages.reactions.delete', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.qr.scan(\n data="x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreaction = client.chats.messages.reactions.delete(\n reaction_key="x",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n message_id="1343993",\n)\nprint(reaction.chat_id)', }, go: { - method: 'client.App.E2ee.Verification.Qr.Scan', + method: 'client.Chats.Messages.Reactions.Delete', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Qr.Scan(context.TODO(), beeperdesktopapi.AppE2eeVerificationQrScanParams{\n\t\tData: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treaction, err := client.Chats.Messages.Reactions.Delete(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.ChatMessageReactionDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tMessageID: "1343993",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reaction.ChatID)\n}\n', }, cli: { - method: 'qr scan', + method: 'reactions delete', example: - "beeper-desktop-cli app:e2ee:verification:qr scan \\\n --access-token 'My Access Token' \\\n --data x", + "beeper-desktop chats:messages:reactions delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --reaction-key x", }, php: { - method: 'app->e2ee->verification->qr->scan', + method: 'chats->messages->reactions->delete', example: - "app->e2ee->verification->qr->scan(data: 'x');\n\nvar_dump($response);", + "chats->messages->reactions->delete(\n 'x', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993'\n);\n\nvar_dump($reaction);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/qr/scan \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "data": "x"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID/reactions/$REACTION_KEY \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'confirm_scanned', - endpoint: '/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned', - httpMethod: 'post', - summary: 'Confirm QR code scan', - description: 'Confirm that another device scanned this device QR code.', - stainlessPath: '(resource) app.e2ee.verification.qr > (method) confirm_scanned', - qualified: 'client.app.e2ee.verification.qr.confirmScanned', - params: ['verificationID: string;'], + name: 'search', + endpoint: '/v1/messages/search', + httpMethod: 'get', + summary: 'Search messages', + description: 'Search messages across chats.', + stainlessPath: '(resource) messages > (method) search', + qualified: 'client.messages.search', + params: [ + 'accountIDs?: string[];', + 'chatIDs?: string[];', + "chatType?: 'group' | 'single';", + 'cursor?: string;', + 'dateAfter?: string;', + 'dateBefore?: string;', + "direction?: 'after' | 'before';", + 'excludeLowPriority?: boolean;', + 'includeMuted?: boolean;', + 'limit?: number;', + "mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[];", + 'query?: string;', + 'sender?: string;', + ], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## confirm_scanned\n\n`client.app.e2ee.verification.qr.confirmScanned(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned`\n\nConfirm that another device scanned this device QR code.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.qr.confirmScanned('x');\n\nconsole.log(response);\n```", + "## search\n\n`client.messages.search(accountIDs?: string[], chatIDs?: string[], chatType?: 'group' | 'single', cursor?: string, dateAfter?: string, dateBefore?: string, direction?: 'after' | 'before', excludeLowPriority?: boolean, includeMuted?: boolean, limit?: number, mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[], query?: string, sender?: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/messages/search`\n\nSearch messages across chats.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit search to specific account IDs.\n\n- `chatIDs?: string[]`\n Limit search to specific chat IDs.\n\n- `chatType?: 'group' | 'single'`\n Filter by chat type: 'group' for group chats, 'single' for 1:1 chats.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `dateAfter?: string`\n Only include messages with timestamp strictly after this ISO 8601 datetime (e.g., '2024-07-01T00:00:00Z' or '2024-07-01T00:00:00+02:00').\n\n- `dateBefore?: string`\n Only include messages with timestamp strictly before this ISO 8601 datetime (e.g., '2024-07-31T23:59:59Z' or '2024-07-31T23:59:59+02:00').\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `excludeLowPriority?: boolean`\n Exclude messages marked Low Priority by the user. Default: true. Set to false to include all.\n\n- `includeMuted?: boolean`\n Include messages in 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.\n\n- `limit?: number`\n Maximum number of messages to return.\n\n- `mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[]`\n Filter messages by media types. Use ['any'] for any media type, or specify exact types like ['video', 'image']. Omit for no media filtering.\n\n- `query?: string`\n Literal word search (non-semantic). Finds messages containing these EXACT words in any order. Use single words users actually type, not concepts or phrases. Example: use \"dinner\" not \"dinner plans\", use \"sick\" not \"health issues\". If omitted, returns results filtered only by other parameters.\n\n- `sender?: string`\n Filter by sender: 'me' (messages sent by the authenticated user), 'others' (messages sent by others), or a specific user ID string (user.id).\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message);\n}\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.qr.confirmScanned', + method: 'client.messages.search', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.qr.confirmScanned('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message.id);\n}", }, python: { - method: 'app.e2ee.verification.qr.confirm_scanned', + method: 'messages.search', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.qr.confirm_scanned(\n "x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.messages.search()\npage = page.items[0]\nprint(page.id)', }, go: { - method: 'client.App.E2ee.Verification.Qr.ConfirmScanned', + method: 'client.Messages.Search', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Qr.ConfirmScanned(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.Search(context.TODO(), beeperdesktopapi.MessageSearchParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'qr confirm_scanned', - example: - "beeper-desktop-cli app:e2ee:verification:qr confirm-scanned \\\n --access-token 'My Access Token' \\\n --verification-id x", + method: 'messages search', + example: "beeper-desktop messages search \\\n --access-token 'My Access Token'", }, php: { - method: 'app->e2ee->verification->qr->confirmScanned', + method: 'messages->search', example: - "app->e2ee->verification->qr->confirmScanned('x');\n\nvar_dump($response);", + "messages->search(\n accountIDs: [\n 'matrix', 'discordgo', 'local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc'\n ],\n chatIDs: ['!NCdzlIaMjZUmvmvyHU:beeper.com', '1231073'],\n chatType: 'group',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n dateAfter: new \\DateTimeImmutable('2025-08-01T00:00:00Z'),\n dateBefore: new \\DateTimeImmutable('2025-08-31T23:59:59Z'),\n direction: 'before',\n excludeLowPriority: true,\n includeMuted: true,\n limit: 20,\n mediaTypes: ['any'],\n query: 'dinner',\n sender: 'sender',\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/qr/confirm-scanned \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/messages/search \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'start', - endpoint: '/v1/app/e2ee/verification/{verificationID}/sas/start', - httpMethod: 'post', - summary: 'Start emoji verification', - description: 'Start emoji comparison for device verification.', - stainlessPath: '(resource) app.e2ee.verification.sas > (method) start', - qualified: 'client.app.e2ee.verification.sas.start', - params: ['verificationID: string;'], + name: 'list', + endpoint: '/v1/chats/{chatID}/messages', + httpMethod: 'get', + summary: 'List messages', + description: 'List all messages in a chat with cursor-based pagination. Sorted by timestamp.', + stainlessPath: '(resource) messages > (method) list', + qualified: 'client.messages.list', + params: ['chatID: string;', 'cursor?: string;', "direction?: 'after' | 'before';"], response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## start\n\n`client.app.e2ee.verification.sas.start(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/sas/start`\n\nStart emoji comparison for device verification.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.sas.start('x');\n\nconsole.log(response);\n```", + "## list\n\n`client.messages.list(chatID: string, cursor?: string, direction?: 'after' | 'before'): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages`\n\nList all messages in a chat with cursor-based pagination. Sorted by timestamp.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message);\n}\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.sas.start', + method: 'client.messages.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.sas.start('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message.id);\n}", }, python: { - method: 'app.e2ee.verification.sas.start', + method: 'messages.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.sas.start(\n "x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\npage = client.messages.list(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\npage = page.items[0]\nprint(page.id)', }, go: { - method: 'client.App.E2ee.Verification.Sas.Start', + method: 'client.Messages.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Sas.Start(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tpage, err := client.Messages.List(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", page)\n}\n', }, cli: { - method: 'sas start', + method: 'messages list', example: - "beeper-desktop-cli app:e2ee:verification:sas start \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop messages list \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->sas->start', + method: 'messages->list', example: - "app->e2ee->verification->sas->start('x');\n\nvar_dump($response);", + "messages->list(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n cursor: '1725489123456|c29tZUltc2dQYWdl',\n direction: 'before',\n);\n\nvar_dump($page);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/sas/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'confirm', - endpoint: '/v1/app/e2ee/verification/{verificationID}/sas/confirm', + name: 'send', + endpoint: '/v1/chats/{chatID}/messages', httpMethod: 'post', - summary: 'Confirm emoji verification', - description: 'Confirm that the emoji or number sequence matches on both devices.', - stainlessPath: '(resource) app.e2ee.verification.sas > (method) confirm', - qualified: 'client.app.e2ee.verification.sas.confirm', - params: ['verificationID: string;'], - response: - "{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }", + summary: 'Send a message', + description: + 'Send a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.', + stainlessPath: '(resource) messages > (method) send', + qualified: 'client.messages.send', + params: [ + 'chatID: string;', + "attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; };", + 'replyToMessageID?: string;', + 'text?: string;', + ], + response: '{ chatID: string; pendingMessageID: string; }', markdown: - "## confirm\n\n`client.app.e2ee.verification.sas.confirm(verificationID: string): { appState: object; }`\n\n**post** `/v1/app/e2ee/verification/{verificationID}/sas/confirm`\n\nConfirm that the emoji or number sequence matches on both devices.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: object; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }; }`\n\n - `appState: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpCode: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryCode: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryCodeGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { availableActions: 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; from?: string; fromDevice?: string; otherDevice?: string; qrData?: string; sas?: { decimals: string; emojis: string; }; supportsSAS?: boolean; supportsScanQRCode?: boolean; verificationID?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.e2ee.verification.sas.confirm('x');\n\nconsole.log(response);\n```", + "## send\n\n`client.messages.send(chatID: string, attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }, replyToMessageID?: string, text?: string): { chatID: string; pendingMessageID: string; }`\n\n**post** `/v1/chats/{chatID}/messages`\n\nSend a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }`\n Single attachment to send with the message\n - `uploadID: string`\n Upload ID from uploadAsset endpoint. Required to reference uploaded files.\n - `duration?: number`\n Duration in seconds (optional override of cached value)\n - `fileName?: string`\n Filename (optional override of cached value)\n - `mimeType?: string`\n MIME type (optional override of cached value)\n - `size?: { height: number; width: number; }`\n Dimensions (optional override of cached value)\n - `type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'`\n Attachment type hint (image, video, audio, file, gif, voice-note, sticker). If omitted, auto-detected from mimeType\n\n- `replyToMessageID?: string`\n Provide a message ID to send this as a reply to an existing message\n\n- `text?: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n\n### Returns\n\n- `{ chatID: string; pendingMessageID: string; }`\n\n - `chatID: string`\n - `pendingMessageID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.app.e2ee.verification.sas.confirm', + method: 'client.messages.send', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.e2ee.verification.sas.confirm('x');\n\nconsole.log(response.appState);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response.pendingMessageID);", }, python: { - method: 'app.e2ee.verification.sas.confirm', + method: 'messages.send', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.e2ee.verification.sas.confirm(\n "x",\n)\nprint(response.app_state)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.messages.send(\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(response.pending_message_id)', }, go: { - method: 'client.App.E2ee.Verification.Sas.Confirm', + method: 'client.Messages.Send', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.E2ee.Verification.Sas.Confirm(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AppState)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Messages.Send(\n\t\tcontext.TODO(),\n\t\t"!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\tbeeperdesktopapi.MessageSendParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.PendingMessageID)\n}\n', }, cli: { - method: 'sas confirm', + method: 'messages send', example: - "beeper-desktop-cli app:e2ee:verification:sas confirm \\\n --access-token 'My Access Token' \\\n --verification-id x", + "beeper-desktop messages send \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com'", }, php: { - method: 'app->e2ee->verification->sas->confirm', + method: 'messages->send', example: - "app->e2ee->verification->sas->confirm('x');\n\nvar_dump($response);", + "messages->send(\n '!NCdzlIaMjZUmvmvyHU:beeper.com',\n attachment: [\n 'uploadID' => 'uploadID',\n 'duration' => 0,\n 'fileName' => 'fileName',\n 'mimeType' => 'mimeType',\n 'size' => ['height' => 0, 'width' => 0],\n 'type' => 'image',\n ],\n replyToMessageID: 'replyToMessageID',\n text: 'text',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/v1/app/e2ee/verification/$VERIFICATION_ID/sas/confirm \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve_profile', - endpoint: '/_matrix/client/v3/profile/{userId}', + name: 'retrieve', + endpoint: '/v1/chats/{chatID}/messages/{messageID}', httpMethod: 'get', - summary: 'Get all profile information for a user.', - description: 'Get the complete profile for a user.', - stainlessPath: '(resource) matrix.users > (method) retrieve_profile', - qualified: 'client.matrix.users.retrieveProfile', - params: ['userId: string;'], - response: '{ avatar_url?: string; displayname?: string; m.tz?: string; }', + summary: 'Retrieve a message', + description: + 'Retrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.', + stainlessPath: '(resource) messages > (method) retrieve', + qualified: 'client.messages.retrieve', + params: ['chatID: string;', 'messageID: string;'], + response: + "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## retrieve_profile\n\n`client.matrix.users.retrieveProfile(userId: string): { avatar_url?: string; displayname?: string; m.tz?: string; }`\n\n**get** `/_matrix/client/v3/profile/{userId}`\n\nGet the complete profile for a user.\n\n### Parameters\n\n- `userId: string`\n\n### Returns\n\n- `{ avatar_url?: string; displayname?: string; m.tz?: string; }`\n\n - `avatar_url?: string`\n - `displayname?: string`\n - `m.tz?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.users.retrieveProfile('@alice:example.com');\n\nconsole.log(response);\n```", + "## retrieve\n\n`client.messages.retrieve(chatID: string, messageID: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages/{messageID}`\n\nRetrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.retrieve('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });\n\nconsole.log(message);\n```", perLanguage: { typescript: { - method: 'client.matrix.users.retrieveProfile', + method: 'client.messages.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.users.retrieveProfile('@alice:example.com');\n\nconsole.log(response.avatar_url);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst message = await client.messages.retrieve('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n});\n\nconsole.log(message.id);", }, python: { - method: 'matrix.users.retrieve_profile', + method: 'messages.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.users.retrieve_profile(\n "@alice:example.com",\n)\nprint(response.avatar_url)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nmessage = client.messages.retrieve(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)\nprint(message.id)', }, go: { - method: 'client.Matrix.Users.GetProfile', + method: 'client.Messages.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Users.GetProfile(context.TODO(), "@alice:example.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.AvatarURL)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Get(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageGetParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message.ID)\n}\n', }, cli: { - method: 'users retrieve_profile', + method: 'messages retrieve', example: - "beeper-desktop-cli matrix:users retrieve-profile \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com", + "beeper-desktop messages retrieve \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", }, php: { - method: 'matrix->users->retrieveProfile', + method: 'messages->retrieve', example: - "matrix->users->retrieveProfile('@alice:example.com');\n\nvar_dump($response);", + "messages->retrieve(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com'\n);\n\nvar_dump($message);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/profile/$USER_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/v3/user/{userId}/account_data/{type}', - httpMethod: 'get', - summary: 'Get some account data for the user.', - description: - 'Get some account data for the client. This config is only visible to the user\nthat set the account data.', - stainlessPath: '(resource) matrix.users.account_data > (method) retrieve', - qualified: 'client.matrix.users.accountData.retrieve', - params: ['userId: string;', 'type: string;'], - response: 'object', + name: 'update', + endpoint: '/v1/chats/{chatID}/messages/{messageID}', + httpMethod: 'put', + summary: 'Edit a message', + description: 'Edit the text content of an existing message. Messages with attachments cannot be edited.', + stainlessPath: '(resource) messages > (method) update', + qualified: 'client.messages.update', + params: ['chatID: string;', 'messageID: string;', 'text: string;'], + response: + "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## retrieve\n\n`client.matrix.users.accountData.retrieve(userId: string, type: string): object`\n\n**get** `/_matrix/client/v3/user/{userId}/account_data/{type}`\n\nGet some account data for the client. This config is only visible to the user\nthat set the account data.\n\n### Parameters\n\n- `userId: string`\n\n- `type: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.users.accountData.retrieve('org.example.custom.config', { userId: '@alice:example.com' });\n\nconsole.log(accountData);\n```", + "## update\n\n`client.messages.update(chatID: string, messageID: string, text: string): object`\n\n**put** `/v1/chats/{chatID}/messages/{messageID}`\n\nEdit the text content of an existing message. Messages with attachments cannot be edited.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `text: string`\n New text content for the message\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.update('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x' });\n\nconsole.log(message);\n```", perLanguage: { typescript: { - method: 'client.matrix.users.accountData.retrieve', + method: 'client.messages.update', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.users.accountData.retrieve('org.example.custom.config', {\n userId: '@alice:example.com',\n});\n\nconsole.log(accountData);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst message = await client.messages.update('1343993', {\n chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com',\n text: 'x',\n});\n\nconsole.log(message);", }, python: { - method: 'matrix.users.account_data.retrieve', + method: 'messages.update', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.users.account_data.retrieve(\n type="org.example.custom.config",\n user_id="@alice:example.com",\n)\nprint(account_data)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nmessage = client.messages.update(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n text="x",\n)\nprint(message)', }, go: { - method: 'client.Matrix.Users.AccountData.Get', + method: 'client.Messages.Update', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Users.AccountData.Get(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.config",\n\t\tbeeperdesktopapi.MatrixUserAccountDataGetParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tmessage, err := client.Messages.Update(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageUpdateParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t\tText: "x",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", message)\n}\n', }, cli: { - method: 'account_data retrieve', + method: 'messages update', example: - "beeper-desktop-cli matrix:users:account-data retrieve \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --type org.example.custom.config", + "beeper-desktop messages update \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993 \\\n --text x", }, php: { - method: 'matrix->users->accountData->retrieve', + method: 'messages->update', example: - "matrix->users->accountData->retrieve(\n 'org.example.custom.config', userID: '@alice:example.com'\n);\n\nvar_dump($accountData);", + "messages->update(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x'\n);\n\nvar_dump($message);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/account_data/$TYPE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "text": "x"\n }\'', }, }, }, { - name: 'update', - endpoint: '/_matrix/client/v3/user/{userId}/account_data/{type}', - httpMethod: 'put', - summary: 'Set some account data for the user.', + name: 'delete', + endpoint: '/v1/chats/{chatID}/messages/{messageID}', + httpMethod: 'delete', + summary: 'Delete a message', description: - 'Set some account data for the client. This config is only visible to the user\nthat set the account data. The config will be available to clients through the\ntop-level `account_data` field in the homeserver response to\n[/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).', - stainlessPath: '(resource) matrix.users.account_data > (method) update', - qualified: 'client.matrix.users.accountData.update', - params: ['userId: string;', 'type: string;', 'body: object;'], - response: 'object', + 'Delete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.', + stainlessPath: '(resource) messages > (method) delete', + qualified: 'client.messages.delete', + params: ['chatID: string;', 'messageID: string;', 'forEveryone?: boolean;'], markdown: - "## update\n\n`client.matrix.users.accountData.update(userId: string, type: string, body: object): object`\n\n**put** `/_matrix/client/v3/user/{userId}/account_data/{type}`\n\nSet some account data for the client. This config is only visible to the user\nthat set the account data. The config will be available to clients through the\ntop-level `account_data` field in the homeserver response to\n[/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).\n\n### Parameters\n\n- `userId: string`\n\n- `type: string`\n\n- `body: object`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.users.accountData.update('org.example.custom.config', {\n userId: '@alice:example.com',\n body: { custom_account_data_key: 'custom_config_value' },\n});\n\nconsole.log(accountData);\n```", + "## delete\n\n`client.messages.delete(chatID: string, messageID: string, forEveryone?: boolean): void`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}`\n\nDelete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `forEveryone?: boolean`\n True to request deletion for everyone when the network supports it; false to delete only for the authenticated user when supported.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' })\n```", perLanguage: { typescript: { - method: 'client.matrix.users.accountData.update', + method: 'client.messages.delete', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.users.accountData.update('org.example.custom.config', {\n userId: '@alice:example.com',\n body: { custom_account_data_key: 'custom_config_value' },\n});\n\nconsole.log(accountData);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });", }, python: { - method: 'matrix.users.account_data.update', + method: 'messages.delete', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.users.account_data.update(\n type="org.example.custom.config",\n user_id="@alice:example.com",\n body={\n "custom_account_data_key": "custom_config_value"\n },\n)\nprint(account_data)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nclient.messages.delete(\n message_id="1343993",\n chat_id="!NCdzlIaMjZUmvmvyHU:beeper.com",\n)', }, go: { - method: 'client.Matrix.Users.AccountData.Update', + method: 'client.Messages.Delete', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Users.AccountData.Update(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.config",\n\t\tbeeperdesktopapi.MatrixUserAccountDataUpdateParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tBody: map[string]any{\n\t\t\t\t"custom_account_data_key": "custom_config_value",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.Messages.Delete(\n\t\tcontext.TODO(),\n\t\t"1343993",\n\t\tbeeperdesktopapi.MessageDeleteParams{\n\t\t\tChatID: "!NCdzlIaMjZUmvmvyHU:beeper.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', }, cli: { - method: 'account_data update', + method: 'messages delete', example: - "beeper-desktop-cli matrix:users:account-data update \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --type org.example.custom.config \\\n --body '{custom_account_data_key: custom_config_value}'", + "beeper-desktop messages delete \\\n --access-token 'My Access Token' \\\n --chat-id '!NCdzlIaMjZUmvmvyHU:beeper.com' \\\n --message-id 1343993", }, php: { - method: 'matrix->users->accountData->update', + method: 'messages->delete', example: - "matrix->users->accountData->update(\n 'org.example.custom.config',\n userID: '@alice:example.com',\n body: ['custom_account_data_key' => 'custom_config_value'],\n);\n\nvar_dump($accountData);", + "messages->delete(\n '1343993', chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', forEveryone: true\n);\n\nvar_dump($result);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/account_data/$TYPE \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "custom_account_data_key": "custom_config_value"\n }\'', + 'curl http://localhost:23373/v1/chats/$CHAT_ID/messages/$MESSAGE_ID \\\n -X DELETE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'create', - endpoint: '/_matrix/client/v3/createRoom', + name: 'download', + endpoint: '/v1/assets/download', httpMethod: 'post', - summary: 'Create a new room', + summary: 'Download a file', description: - "Create a new room with various configuration options.\n\nThe server MUST apply the normal state resolution rules when creating\nthe new room, including checking power levels for each event. It MUST\napply the events implied by the request in the following order:\n\n1. The `m.room.create` event itself. Must be the first event in the\n room.\n\n2. An `m.room.member` event for the creator to join the room. This is\n needed so the remaining events can be sent.\n\n3. A default `m.room.power_levels` event. Overridden by the\n `power_level_content_override` parameter.\n\n In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the room creator (and not\n other members) will be given permission to send state events.\n\n In room versions 12 and later, the room creator is given infinite\n power level and cannot be specified in the `users` field of\n `m.room.power_levels`, so is not listed explicitly.\n\n **Note**: For `trusted_private_chat`, the users specified in the\n `invite` parameter SHOULD also be appended to `additional_creators`\n by the server, per the `creation_content` parameter.\n\n If the room's version is 12 or higher, the power level for sending\n `m.room.tombstone` events MUST explicitly be higher than `state_default`.\n For example, set to 150 instead of 100.\n\n4. An `m.room.canonical_alias` event if `room_alias_name` is given.\n\n5. Events set by the `preset`. Currently these are the `m.room.join_rules`,\n `m.room.history_visibility`, and `m.room.guest_access` state events.\n\n6. Events listed in `initial_state`, in the order that they are\n listed.\n\n7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`\n state events).\n\n8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with\n `membership: invite` and `m.room.third_party_invite`).\n\nThe available presets do the following with respect to room state:\n\n| Preset | `join_rules` | `history_visibility` | `guest_access` | Other |\n|------------------------|--------------|----------------------|----------------|-------|\n| `private_chat` | `invite` | `shared` | `can_join` | |\n| `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. |\n| `public_chat` | `public` | `shared` | `forbidden` | |\n\nThe server will create a `m.room.create` event in the room with the\nrequesting user as the creator, alongside other keys provided in the\n`creation_content` or implied by behaviour of `creation_content`.", - stainlessPath: '(resource) matrix.rooms > (method) create', - qualified: 'client.matrix.rooms.create', - params: [ - 'creation_content?: object;', - 'initial_state?: { content: object; type: string; state_key?: string; }[];', - 'invite?: string[];', - 'invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[];', - 'is_direct?: boolean;', - 'name?: string;', - 'power_level_content_override?: object;', - "preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat';", - 'room_alias_name?: string;', - 'room_version?: string;', - 'topic?: string;', - "visibility?: 'public' | 'private';", - ], - response: '{ room_id: string; }', + 'Download a Matrix file using its mxc:// or localmxc:// URL to the device running Beeper Desktop and return the local file URL.', + stainlessPath: '(resource) assets > (method) download', + qualified: 'client.assets.download', + params: ['url: string;'], + response: '{ error?: string; srcURL?: string; }', markdown: - "## create\n\n`client.matrix.rooms.create(creation_content?: object, initial_state?: { content: object; type: string; state_key?: string; }[], invite?: string[], invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[], is_direct?: boolean, name?: string, power_level_content_override?: object, preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat', room_alias_name?: string, room_version?: string, topic?: string, visibility?: 'public' | 'private'): { room_id: string; }`\n\n**post** `/_matrix/client/v3/createRoom`\n\nCreate a new room with various configuration options.\n\nThe server MUST apply the normal state resolution rules when creating\nthe new room, including checking power levels for each event. It MUST\napply the events implied by the request in the following order:\n\n1. The `m.room.create` event itself. Must be the first event in the\n room.\n\n2. An `m.room.member` event for the creator to join the room. This is\n needed so the remaining events can be sent.\n\n3. A default `m.room.power_levels` event. Overridden by the\n `power_level_content_override` parameter.\n\n In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the room creator (and not\n other members) will be given permission to send state events.\n\n In room versions 12 and later, the room creator is given infinite\n power level and cannot be specified in the `users` field of\n `m.room.power_levels`, so is not listed explicitly.\n\n **Note**: For `trusted_private_chat`, the users specified in the\n `invite` parameter SHOULD also be appended to `additional_creators`\n by the server, per the `creation_content` parameter.\n\n If the room's version is 12 or higher, the power level for sending\n `m.room.tombstone` events MUST explicitly be higher than `state_default`.\n For example, set to 150 instead of 100.\n\n4. An `m.room.canonical_alias` event if `room_alias_name` is given.\n\n5. Events set by the `preset`. Currently these are the `m.room.join_rules`,\n `m.room.history_visibility`, and `m.room.guest_access` state events.\n\n6. Events listed in `initial_state`, in the order that they are\n listed.\n\n7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic`\n state events).\n\n8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with\n `membership: invite` and `m.room.third_party_invite`).\n\nThe available presets do the following with respect to room state:\n\n| Preset | `join_rules` | `history_visibility` | `guest_access` | Other |\n|------------------------|--------------|----------------------|----------------|-------|\n| `private_chat` | `invite` | `shared` | `can_join` | |\n| `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. |\n| `public_chat` | `public` | `shared` | `forbidden` | |\n\nThe server will create a `m.room.create` event in the room with the\nrequesting user as the creator, alongside other keys provided in the\n`creation_content` or implied by behaviour of `creation_content`.\n\n### Parameters\n\n- `creation_content?: object`\n Extra keys, such as `m.federate`, to be added to the content\nof the [`m.room.create`](https://spec.matrix.org/v1.18/client-server-api/#mroomcreate) event.\n\nThe server will overwrite the following\nkeys: `creator`, `room_version`. Future versions of the specification\nmay allow the server to overwrite other keys.\n\nWhen using the `trusted_private_chat` preset, the server SHOULD combine\n`additional_creators` specified here and the `invite` array into the\neventual `m.room.create` event's `additional_creators`, deduplicating\nbetween the two parameters.\n\n- `initial_state?: { content: object; type: string; state_key?: string; }[]`\n A list of state events to set in the new room. This allows\nthe user to override the default state events set in the new\nroom. The expected format of the state events are an object\nwith type, state_key and content keys set.\n\nTakes precedence over events set by `preset`, but gets\noverridden by `name` and `topic` keys.\n\n- `invite?: string[]`\n A list of user IDs to invite to the room. This will tell the\nserver to invite everyone in the list to the newly created room.\n\n- `invite_3pid?: { address: string; id_access_token: string; id_server: string; medium: string; }[]`\n A list of objects representing third-party IDs to invite into\nthe room.\n\n- `is_direct?: boolean`\n This flag makes the server set the `is_direct` flag on the\n`m.room.member` events sent to the users in `invite` and\n`invite_3pid`. See [Direct Messaging](https://spec.matrix.org/v1.18/client-server-api/#direct-messaging) for more information.\n\n- `name?: string`\n If this is included, an [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname) event\nwill be sent into the room to indicate the name for the room.\nThis overwrites any [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname)\nevent in `initial_state`.\n\n- `power_level_content_override?: object`\n The power level content to override in the default power level\nevent. This object is applied on top of the generated\n[`m.room.power_levels`](https://spec.matrix.org/v1.18/client-server-api/#mroompower_levels)\nevent content prior to it being sent to the room. Defaults to\noverriding nothing.\n\n- `preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat'`\n Convenience parameter for setting various default state events\nbased on a preset.\n\nIf unspecified, the server should use the `visibility` to determine\nwhich preset to use. A visibility of `public` equates to a preset of\n`public_chat` and `private` visibility equates to a preset of\n`private_chat`.\n\n- `room_alias_name?: string`\n The desired room alias **local part**. If this is included, a\nroom alias will be created and mapped to the newly created\nroom. The alias will belong on the *same* homeserver which\ncreated the room. For example, if this was set to \"foo\" and\nsent to the homeserver \"example.com\" the complete room alias\nwould be `#foo:example.com`.\n\nThe complete room alias will become the canonical alias for\nthe room and an `m.room.canonical_alias` event will be sent\ninto the room.\n\n- `room_version?: string`\n The room version to set for the room. If not provided, the homeserver is\nto use its configured default. If provided, the homeserver will return a\n400 error with the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not\nsupport the room version.\n\n- `topic?: string`\n If this is included, an [`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic)\nevent with a `text/plain` mimetype will be sent into the room\nto indicate the topic for the room. This overwrites any\n[`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic) event in `initial_state`.\n\n- `visibility?: 'public' | 'private'`\n The room's visibility in the server's\n[published room directory](https://spec.matrix.org/v1.18/client-server-api#published-room-directory).\nDefaults to `private`.\n\n### Returns\n\n- `{ room_id: string; }`\n Information about the newly created room.\n\n - `room_id: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst room = await client.matrix.rooms.create();\n\nconsole.log(room);\n```", + "## download\n\n`client.assets.download(url: string): { error?: string; srcURL?: string; }`\n\n**post** `/v1/assets/download`\n\nDownload a Matrix file using its mxc:// or localmxc:// URL to the device running Beeper Desktop and return the local file URL.\n\n### Parameters\n\n- `url: string`\n Matrix content URL (mxc:// or localmxc://) for the file to download.\n\n### Returns\n\n- `{ error?: string; srcURL?: string; }`\n\n - `error?: string`\n - `srcURL?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.create', + method: 'client.assets.download', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst room = await client.matrix.rooms.create();\n\nconsole.log(room.room_id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response.error);", }, python: { - method: 'matrix.rooms.create', + method: 'assets.download', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nroom = client.matrix.rooms.create()\nprint(room.room_id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.download(\n url="mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n)\nprint(response.error)', }, go: { - method: 'client.Matrix.Rooms.New', + method: 'client.Assets.Download', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\troom, err := client.Matrix.Rooms.New(context.TODO(), beeperdesktopapi.MatrixRoomNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", room.RoomID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Download(context.TODO(), beeperdesktopapi.AssetDownloadParams{\n\t\tURL: "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Error)\n}\n', }, cli: { - method: 'rooms create', - example: "beeper-desktop-cli matrix:rooms create \\\n --access-token 'My Access Token'", + method: 'assets download', + example: + "beeper-desktop assets download \\\n --access-token 'My Access Token' \\\n --url mxc://example.org/Q4x9CqGz1pB3Oa6XgJ", }, php: { - method: 'matrix->rooms->create', + method: 'assets->download', example: - "matrix->rooms->create(\n creationContent: ['m.federate' => false],\n initialState: [\n ['content' => (object) [], 'type' => 'type', 'stateKey' => 'state_key']\n ],\n invite: ['string'],\n invite3pid: [\n [\n 'address' => 'cheeky@monkey.com',\n 'idAccessToken' => 'abc123_OpaqueString',\n 'idServer' => 'matrix.org',\n 'medium' => 'email',\n ],\n ],\n isDirect: true,\n name: 'The Grand Duke Pub',\n powerLevelContentOverride: (object) [],\n preset: 'public_chat',\n roomAliasName: 'thepub',\n roomVersion: '1',\n topic: 'All about happy hour',\n visibility: 'public',\n);\n\nvar_dump($room);", + "assets->download(\n url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/createRoom \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "creation_content": {\n "m.federate": false\n },\n "name": "The Grand Duke Pub",\n "preset": "public_chat",\n "room_alias_name": "thepub",\n "room_version": "1",\n "topic": "All about happy hour"\n }\'', + 'curl http://localhost:23373/v1/assets/download \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "url": "mxc://example.org/Q4x9CqGz1pB3Oa6XgJ"\n }\'', }, }, }, { - name: 'join', - endpoint: '/_matrix/client/v3/join/{roomIdOrAlias}', + name: 'upload', + endpoint: '/v1/assets/upload', httpMethod: 'post', - summary: 'Join the requesting user to a particular room.', + summary: 'Upload a file', description: - "*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.\n\nThis API starts a user's participation in a particular room, if that user\nis allowed to participate in that room. After this call, the client is\nallowed to see all current state events in the room, and all subsequent\nevents associated with the room until the user leaves the room.\n\nAfter a user has joined a room, the room will appear as an entry in the\nresponse of the [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync)\nand [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) APIs.", - stainlessPath: '(resource) matrix.rooms > (method) join', - qualified: 'client.matrix.rooms.join', - params: [ - 'roomIdOrAlias: string;', - 'via?: string[];', - 'reason?: string;', - 'third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; };', - ], - response: '{ room_id: string; }', + '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.', + stainlessPath: '(resource) assets > (method) upload', + qualified: 'client.assets.upload', + params: ['file: string;', 'fileName?: string;', 'mimeType?: string;'], + response: + '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', markdown: - "## join\n\n`client.matrix.rooms.join(roomIdOrAlias: string, via?: string[], reason?: string, third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; }): { room_id: string; }`\n\n**post** `/_matrix/client/v3/join/{roomIdOrAlias}`\n\n*Note that this API takes either a room ID or alias, unlike* `/rooms/{roomId}/join`.\n\nThis API starts a user's participation in a particular room, if that user\nis allowed to participate in that room. After this call, the client is\nallowed to see all current state events in the room, and all subsequent\nevents associated with the room until the user leaves the room.\n\nAfter a user has joined a room, the room will appear as an entry in the\nresponse of the [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync)\nand [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) APIs.\n\n### Parameters\n\n- `roomIdOrAlias: string`\n\n- `via?: string[]`\n The servers to attempt to join the room through. One of the servers\nmust be participating in the room.\n\n- `reason?: string`\n Optional reason to be included as the `reason` on the subsequent\nmembership event.\n\n- `third_party_signed?: { token: string; mxid: string; sender: string; signatures: object; }`\n A signature of an `m.third_party_invite` token to prove that this user\nowns a third-party identity which has been invited to the room.\n - `token: string`\n The state key of the m.third_party_invite event.\n - `mxid: string`\n The Matrix ID of the invitee.\n - `sender: string`\n The Matrix ID of the user who issued the invite.\n - `signatures: object`\n A signatures object containing a signature of the entire signed object.\n\n### Returns\n\n- `{ room_id: string; }`\n\n - `room_id: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.rooms.join('!monkeys:matrix.org');\n\nconsole.log(response);\n```", + "## upload\n\n`client.assets.upload(file: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload`\n\nUpload 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.\n\n### Parameters\n\n- `file: string`\n The file to upload (max 500 MB).\n\n- `fileName?: string`\n Original filename. Defaults to the uploaded file name if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.join', + method: 'client.assets.upload', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.rooms.join('!monkeys:matrix.org');\n\nconsole.log(response.room_id);", + "import fs from 'fs';\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response.width);", }, python: { - method: 'matrix.rooms.join', + method: 'assets.upload', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.rooms.join(\n room_id_or_alias="!monkeys:matrix.org",\n)\nprint(response.room_id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.upload(\n file=b"Example data",\n)\nprint(response.width)', }, go: { - method: 'client.Matrix.Rooms.Join', + method: 'client.Assets.Upload', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Rooms.Join(\n\t\tcontext.TODO(),\n\t\t"!monkeys:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomJoinParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.RoomID)\n}\n', + 'package main\n\nimport (\n\t"bytes"\n\t"context"\n\t"fmt"\n\t"io"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Upload(context.TODO(), beeperdesktopapi.AssetUploadParams{\n\t\tFile: io.Reader(bytes.NewBuffer([]byte("Example data"))),\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', }, cli: { - method: 'rooms join', + method: 'assets upload', example: - "beeper-desktop-cli matrix:rooms join \\\n --access-token 'My Access Token' \\\n --room-id-or-alias '!monkeys:matrix.org'", + "beeper-desktop assets upload \\\n --access-token 'My Access Token' \\\n --file 'Example data'", }, php: { - method: 'matrix->rooms->join', + method: 'assets->upload', example: - "matrix->rooms->join(\n '!monkeys:matrix.org',\n via: ['string'],\n reason: 'Looking for support',\n thirdPartySigned: [\n 'token' => 'random8nonce',\n 'mxid' => 'bob',\n 'sender' => 'alice',\n 'signatures' => ['example.org' => ['ed25519:0' => 'some9signature']],\n ],\n);\n\nvar_dump($response);", + "assets->upload(\n file: FileParam::fromString('Example data', filename: uniqid('file-upload-', true)),\n fileName: 'fileName',\n mimeType: 'mimeType',\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/join/$ROOM_ID_OR_ALIAS \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reason": "Looking for support"\n }\'', + "curl http://localhost:23373/v1/assets/upload \\\n -H 'Content-Type: multipart/form-data' \\\n -H \"Authorization: Bearer $BEEPER_ACCESS_TOKEN\" \\\n -F 'file=@/path/to/file'", }, }, }, { - name: 'leave', - endpoint: '/_matrix/client/v3/rooms/{roomId}/leave', + name: 'upload_base64', + endpoint: '/v1/assets/upload/base64', httpMethod: 'post', - summary: 'Stop the requesting user participating in a particular room.', + summary: 'Upload a file (base64)', description: - "This API stops a user participating in a particular room.\n\nIf the user was already in the room, they will no longer be able to see\nnew events in the room. If the room requires an invite to join, they\nwill need to be re-invited before they can re-join.\n\nIf the user was invited to the room, but had not joined, this call\nserves to reject the invite.\n\nServers MAY additionally forget the room when this endpoint is called –\njust as if the user had also invoked [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget).\nServers that do this, MUST inform clients about this behavior using the\n[`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability)\ncapability.\n\nIf the server doesn't automatically forget the room, the user will still be\nallowed to retrieve history from the room which they were previously allowed\nto see.", - stainlessPath: '(resource) matrix.rooms > (method) leave', - qualified: 'client.matrix.rooms.leave', - params: ['roomId: string;', 'reason?: string;'], - response: 'object', + '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.', + stainlessPath: '(resource) assets > (method) upload_base64', + qualified: 'client.assets.uploadBase64', + params: ['content: string;', 'fileName?: string;', 'mimeType?: string;'], + response: + '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', markdown: - "## leave\n\n`client.matrix.rooms.leave(roomId: string, reason?: string): object`\n\n**post** `/_matrix/client/v3/rooms/{roomId}/leave`\n\nThis API stops a user participating in a particular room.\n\nIf the user was already in the room, they will no longer be able to see\nnew events in the room. If the room requires an invite to join, they\nwill need to be re-invited before they can re-join.\n\nIf the user was invited to the room, but had not joined, this call\nserves to reject the invite.\n\nServers MAY additionally forget the room when this endpoint is called –\njust as if the user had also invoked [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget).\nServers that do this, MUST inform clients about this behavior using the\n[`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability)\ncapability.\n\nIf the server doesn't automatically forget the room, the user will still be\nallowed to retrieve history from the room which they were previously allowed\nto see.\n\n### Parameters\n\n- `roomId: string`\n\n- `reason?: string`\n Optional reason to be included as the `reason` on the subsequent\nmembership event.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.rooms.leave('!nkl290a:matrix.org');\n\nconsole.log(response);\n```", + "## upload_base64\n\n`client.assets.uploadBase64(content: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload/base64`\n\nUpload 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.\n\n### Parameters\n\n- `content: string`\n Base64-encoded file content (max ~500MB decoded)\n\n- `fileName?: string`\n Original filename. Generated if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.leave', + method: 'client.assets.uploadBase64', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.rooms.leave('!nkl290a:matrix.org');\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response.width);", }, python: { - method: 'matrix.rooms.leave', + method: 'assets.upload_base64', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.rooms.leave(\n room_id="!nkl290a:matrix.org",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.upload_base64(\n content="x",\n)\nprint(response.width)', }, go: { - method: 'client.Matrix.Rooms.Leave', + method: 'client.Assets.UploadBase64', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Rooms.Leave(\n\t\tcontext.TODO(),\n\t\t"!nkl290a:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomLeaveParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.UploadBase64(context.TODO(), beeperdesktopapi.AssetUploadBase64Params{\n\t\tContent: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Width)\n}\n', }, cli: { - method: 'rooms leave', + method: 'assets upload_base64', example: - "beeper-desktop-cli matrix:rooms leave \\\n --access-token 'My Access Token' \\\n --room-id '!nkl290a:matrix.org'", + "beeper-desktop assets upload-base64 \\\n --access-token 'My Access Token' \\\n --content x", }, php: { - method: 'matrix->rooms->leave', + method: 'assets->uploadBase64', example: - "matrix->rooms->leave(\n '!nkl290a:matrix.org', reason: 'Saying farewell - thanks for the support!'\n);\n\nvar_dump($response);", + "assets->uploadBase64(\n content: 'x', fileName: 'fileName', mimeType: 'mimeType'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/leave \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "reason": "Saying farewell - thanks for the support!"\n }\'', + 'curl http://localhost:23373/v1/assets/upload/base64 \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "content": "x"\n }\'', }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', + name: 'serve', + endpoint: '/v1/assets/serve', httpMethod: 'get', - summary: 'Get some account data for the user that is specific to a room.', + summary: 'Serve a file', description: - 'Get some account data for the client on a given room. This config is only\nvisible to the user that set the account data.', - stainlessPath: '(resource) matrix.rooms.account_data > (method) retrieve', - qualified: 'client.matrix.rooms.accountData.retrieve', - params: ['userId: string;', 'roomId: string;', 'type: string;'], - response: 'object', + 'Stream a file given an mxc://, localmxc://, or file:// URL. Downloads first if not cached. Supports Range requests for seeking in large files.', + stainlessPath: '(resource) assets > (method) serve', + qualified: 'client.assets.serve', + params: ['url: string;'], + response: 'string', markdown: - "## retrieve\n\n`client.matrix.rooms.accountData.retrieve(userId: string, roomId: string, type: string): object`\n\n**get** `/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}`\n\nGet some account data for the client on a given room. This config is only\nvisible to the user that set the account data.\n\n### Parameters\n\n- `userId: string`\n\n- `roomId: string`\n\n- `type: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.rooms.accountData.retrieve('org.example.custom.room.config', { userId: '@alice:example.com', roomId: '!726s6s6q:example.com' });\n\nconsole.log(accountData);\n```", + "## serve\n\n`client.assets.serve(url: string): string`\n\n**get** `/v1/assets/serve`\n\nStream a file given an mxc://, localmxc://, or file:// URL. Downloads first if not cached. Supports Range requests for seeking in large files.\n\n### Parameters\n\n- `url: string`\n File URL to serve. Accepts mxc://, localmxc://, or file:// URLs.\n\n### Returns\n\n- `string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.serve({ url: 'x' });\n\nconsole.log(response);\n\nconst content = await response.blob()\nconsole.log(content)\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.accountData.retrieve', + method: 'client.assets.serve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.rooms.accountData.retrieve(\n 'org.example.custom.room.config',\n { userId: '@alice:example.com', roomId: '!726s6s6q:example.com' },\n);\n\nconsole.log(accountData);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.assets.serve({ url: 'x' });\n\nconsole.log(response);\n\nconst content = await response.blob();\nconsole.log(content);", }, python: { - method: 'matrix.rooms.account_data.retrieve', + method: 'assets.serve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.rooms.account_data.retrieve(\n type="org.example.custom.room.config",\n user_id="@alice:example.com",\n room_id="!726s6s6q:example.com",\n)\nprint(account_data)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.assets.serve(\n url="x",\n)\nprint(response)\ncontent = response.read()\nprint(content)', }, go: { - method: 'client.Matrix.Rooms.AccountData.Get', + method: 'client.Assets.Serve', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Rooms.AccountData.Get(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.room.config",\n\t\tbeeperdesktopapi.MatrixRoomAccountDataGetParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tRoomID: "!726s6s6q:example.com",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Assets.Serve(context.TODO(), beeperdesktopapi.AssetServeParams{\n\t\tURL: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'account_data retrieve', - example: - "beeper-desktop-cli matrix:rooms:account-data retrieve \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --room-id '!726s6s6q:example.com' \\\n --type org.example.custom.room.config", + method: 'assets serve', + example: "beeper-desktop assets serve \\\n --access-token 'My Access Token' \\\n --url x", }, php: { - method: 'matrix->rooms->accountData->retrieve', + method: 'assets->serve', example: - "matrix->rooms->accountData->retrieve(\n 'org.example.custom.room.config',\n userID: '@alice:example.com',\n roomID: '!726s6s6q:example.com',\n);\n\nvar_dump($accountData);", + "assets->serve(url: 'x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/rooms/$ROOM_ID/account_data/$TYPE \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/assets/serve \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'update', - endpoint: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', - httpMethod: 'put', - summary: 'Set some account data for the user that is specific to a room.', + name: 'retrieve', + endpoint: '/v1/info', + httpMethod: 'get', + summary: 'Retrieve server info', description: - 'Set some account data for the client on a given room. This config is only\nvisible to the user that set the account data. The config will be delivered to\nclients in the per-room entries via [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).', - stainlessPath: '(resource) matrix.rooms.account_data > (method) update', - qualified: 'client.matrix.rooms.accountData.update', - params: ['userId: string;', 'roomId: string;', 'type: string;', 'body: object;'], - response: 'object', + 'Returns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.', + stainlessPath: '(resource) info > (method) retrieve', + qualified: 'client.info.retrieve', + response: + '{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }', markdown: - "## update\n\n`client.matrix.rooms.accountData.update(userId: string, roomId: string, type: string, body: object): object`\n\n**put** `/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}`\n\nSet some account data for the client on a given room. This config is only\nvisible to the user that set the account data. The config will be delivered to\nclients in the per-room entries via [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync).\n\n### Parameters\n\n- `userId: string`\n\n- `roomId: string`\n\n- `type: string`\n\n- `body: object`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accountData = await client.matrix.rooms.accountData.update('org.example.custom.room.config', {\n userId: '@alice:example.com',\n roomId: '!726s6s6q:example.com',\n body: { custom_account_data_key: 'custom_account_data_value' },\n});\n\nconsole.log(accountData);\n```", + "## retrieve\n\n`client.info.retrieve(): { app: object; endpoints: object; platform: object; server: object; }`\n\n**get** `/v1/info`\n\nReturns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.\n\n### Returns\n\n- `{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }`\n\n - `app: { bundle_id: string; name: string; version: string; }`\n - `endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }`\n - `platform: { arch: string; os: string; release?: string; }`\n - `server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.accountData.update', + method: 'client.info.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst accountData = await client.matrix.rooms.accountData.update('org.example.custom.room.config', {\n userId: '@alice:example.com',\n roomId: '!726s6s6q:example.com',\n body: { custom_account_data_key: 'custom_account_data_value' },\n});\n\nconsole.log(accountData);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info.app);", }, python: { - method: 'matrix.rooms.account_data.update', + method: 'info.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\naccount_data = client.matrix.rooms.account_data.update(\n type="org.example.custom.room.config",\n user_id="@alice:example.com",\n room_id="!726s6s6q:example.com",\n body={\n "custom_account_data_key": "custom_account_data_value"\n },\n)\nprint(account_data)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\ninfo = client.info.retrieve()\nprint(info.app)', }, go: { - method: 'client.Matrix.Rooms.AccountData.Update', + method: 'client.Info.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\taccountData, err := client.Matrix.Rooms.AccountData.Update(\n\t\tcontext.TODO(),\n\t\t"org.example.custom.room.config",\n\t\tbeeperdesktopapi.MatrixRoomAccountDataUpdateParams{\n\t\t\tUserID: "@alice:example.com",\n\t\t\tRoomID: "!726s6s6q:example.com",\n\t\t\tBody: map[string]any{\n\t\t\t\t"custom_account_data_key": "custom_account_data_value",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", accountData)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tinfo, err := client.Info.Get(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", info.App)\n}\n', }, cli: { - method: 'account_data update', - example: - "beeper-desktop-cli matrix:rooms:account-data update \\\n --access-token 'My Access Token' \\\n --user-id @alice:example.com \\\n --room-id '!726s6s6q:example.com' \\\n --type org.example.custom.room.config \\\n --body '{custom_account_data_key: custom_account_data_value}'", + method: 'info retrieve', + example: "beeper-desktop info retrieve \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->rooms->accountData->update', + method: 'info->retrieve', example: - "matrix->rooms->accountData->update(\n 'org.example.custom.room.config',\n userID: '@alice:example.com',\n roomID: '!726s6s6q:example.com',\n body: ['custom_account_data_key' => 'custom_account_data_value'],\n);\n\nvar_dump($accountData);", + "info->retrieve();\n\nvar_dump($info);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/user/$USER_ID/rooms/$ROOM_ID/account_data/$TYPE \\\n -X PUT \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "custom_account_data_key": "custom_account_data_value"\n }\'', + 'curl http://localhost:23373/v1/info \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'list', - endpoint: '/_matrix/client/v3/rooms/{roomId}/state', + name: 'session', + endpoint: '/v1/app/session', httpMethod: 'get', - summary: 'Get all state events in the current state of a room.', - description: 'Get the state events for the current state of a room.', - stainlessPath: '(resource) matrix.rooms.state > (method) list', - qualified: 'client.matrix.rooms.state.list', - params: ['roomId: string;'], + summary: 'Get app session', + description: + 'Return the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.', + stainlessPath: '(resource) app > (method) session', + qualified: 'client.app.session', response: - '{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }[]', + "{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }", markdown: - "## list\n\n`client.matrix.rooms.state.list(roomId: string): { content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: object; }[]`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/state`\n\nGet the state events for the current state of a room.\n\n### Parameters\n\n- `roomId: string`\n\n### Returns\n\n- `{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }[]`\n If the user is a member of the room this will be the\ncurrent state of the room as a list of events. If the user\nhas left the room then this will be the state of the room\nwhen they left as a list of events.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst states = await client.matrix.rooms.state.list('!636q39766251:example.com');\n\nconsole.log(states);\n```", + "## session\n\n`client.app.session(): { e2ee: object; state: string; matrix?: object; verification?: object; }`\n\n**get** `/v1/app/session`\n\nReturn the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.\n\n### Returns\n\n- `{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }`\n - `state: string`\n - `matrix?: { deviceID: string; homeserver: string; userID: string; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.session();\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.state.list', + method: 'client.app.session', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst states = await client.matrix.rooms.state.list('!636q39766251:example.com');\n\nconsole.log(states);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.session();\n\nconsole.log(response.e2ee);", }, python: { - method: 'matrix.rooms.state.list', + method: 'app.session', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nstates = client.matrix.rooms.state.list(\n "!636q39766251:example.com",\n)\nprint(states)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.session()\nprint(response.e2ee)', }, go: { - method: 'client.Matrix.Rooms.State.List', + method: 'client.App.Session', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tstates, err := client.Matrix.Rooms.State.List(context.TODO(), "!636q39766251:example.com")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", states)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Session(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.E2EE)\n}\n', }, cli: { - method: 'state list', - example: - "beeper-desktop-cli matrix:rooms:state list \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:example.com'", + method: 'app session', + example: "beeper-desktop app session \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->rooms->state->list', + method: 'app->session', example: - "matrix->rooms->state->list('!636q39766251:example.com');\n\nvar_dump($states);", + "app->session();\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/state \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/session \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}', - httpMethod: 'get', - summary: 'Get the state identified by the type and key.', - description: - 'Looks up the contents of a state event in a room. If the user is\njoined to the room then the state is taken from the current\nstate of the room. If the user has left the room then the state is\ntaken from the state of the room when they left.', - stainlessPath: '(resource) matrix.rooms.state > (method) retrieve', - qualified: 'client.matrix.rooms.state.retrieve', - params: ['roomId: string;', 'eventType: string;', 'stateKey: string;', "format?: 'content' | 'event';"], - response: 'object', + name: 'start', + endpoint: '/v1/app/login/start', + httpMethod: 'post', + summary: 'Start app login', + description: 'Start a first-party Beeper Desktop sign-in session.', + stainlessPath: '(resource) app.login > (method) start', + qualified: 'client.app.login.start', + response: '{ request: string; type: string[]; }', markdown: - "## retrieve\n\n`client.matrix.rooms.state.retrieve(roomId: string, eventType: string, stateKey: string, format?: 'content' | 'event'): object`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}`\n\nLooks up the contents of a state event in a room. If the user is\njoined to the room then the state is taken from the current\nstate of the room. If the user has left the room then the state is\ntaken from the state of the room when they left.\n\n### Parameters\n\n- `roomId: string`\n\n- `eventType: string`\n\n- `stateKey: string`\n\n- `format?: 'content' | 'event'`\n The format to use for the returned data. `content` (the default) will\nreturn only the content of the state event. `event` will return the entire\nevent in the usual format suitable for clients, including fields like event\nID, sender and timestamp.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst state = await client.matrix.rooms.state.retrieve('state_key', { roomId: '!636q39766251:example.com', eventType: 'm.room.name' });\n\nconsole.log(state);\n```", + "## start\n\n`client.app.login.start(): { request: string; type: string[]; }`\n\n**post** `/v1/app/login/start`\n\nStart a first-party Beeper Desktop sign-in session.\n\n### Returns\n\n- `{ request: string; type: string[]; }`\n\n - `request: string`\n - `type: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.state.retrieve', + method: 'client.app.login.start', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst state = await client.matrix.rooms.state.retrieve('state_key', {\n roomId: '!636q39766251:example.com',\n eventType: 'm.room.name',\n});\n\nconsole.log(state);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response.request);", }, python: { - method: 'matrix.rooms.state.retrieve', + method: 'app.login.start', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nstate = client.matrix.rooms.state.retrieve(\n state_key="state_key",\n room_id="!636q39766251:example.com",\n event_type="m.room.name",\n)\nprint(state)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.start()\nprint(response.request)', }, go: { - method: 'client.Matrix.Rooms.State.Get', + method: 'client.App.Login.Start', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tstate, err := client.Matrix.Rooms.State.Get(\n\t\tcontext.TODO(),\n\t\t"state_key",\n\t\tbeeperdesktopapi.MatrixRoomStateGetParams{\n\t\t\tRoomID: "!636q39766251:example.com",\n\t\t\tEventType: "m.room.name",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", state)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Start(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Request)\n}\n', }, cli: { - method: 'state retrieve', - example: - "beeper-desktop-cli matrix:rooms:state retrieve \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:example.com' \\\n --event-type m.room.name \\\n --state-key state_key", + method: 'login start', + example: "beeper-desktop app:login start \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->rooms->state->retrieve', + method: 'app->login->start', example: - "matrix->rooms->state->retrieve(\n 'state_key',\n roomID: '!636q39766251:example.com',\n eventType: 'm.room.name',\n format: 'content',\n);\n\nvar_dump($state);", + "app->login->start();\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/state/$EVENT_TYPE/$STATE_KEY \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/v3/rooms/{roomId}/event/{eventId}', - httpMethod: 'get', - summary: 'Get a single event by event ID.', - description: - 'Get a single event based on `roomId/eventId`. You must have permission to\nretrieve this event e.g. by being a member in the room for this event.', - stainlessPath: '(resource) matrix.rooms.events > (method) retrieve', - qualified: 'client.matrix.rooms.events.retrieve', - params: ['roomId: string;', 'eventId: string;'], - response: - '{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }', + name: 'email', + endpoint: '/v1/app/login/email', + httpMethod: 'post', + summary: 'Send login code', + description: 'Send a sign-in code to the user email address.', + stainlessPath: '(resource) app.login > (method) email', + qualified: 'client.app.login.email', + params: ['email: string;', 'request: string;'], + response: 'object', markdown: - "## retrieve\n\n`client.matrix.rooms.events.retrieve(roomId: string, eventId: string): { content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: object; }`\n\n**get** `/_matrix/client/v3/rooms/{roomId}/event/{eventId}`\n\nGet a single event based on `roomId/eventId`. You must have permission to\nretrieve this event e.g. by being a member in the room for this event.\n\n### Parameters\n\n- `roomId: string`\n\n- `eventId: string`\n\n### Returns\n\n- `{ content: object; event_id: string; origin_server_ts: number; room_id: string; sender: string; type: string; state_key?: string; unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }; }`\n The format used for events when they are returned from a homeserver to a client\nvia the Client-Server API, or sent to an Application Service via the Application Services API.\n\n - `content: object`\n - `event_id: string`\n - `origin_server_ts: number`\n - `room_id: string`\n - `sender: string`\n - `type: string`\n - `state_key?: string`\n - `unsigned?: { age?: number; membership?: string; prev_content?: object; redacted_because?: object; transaction_id?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst event = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', { roomId: '!636q39766251:matrix.org' });\n\nconsole.log(event);\n```", + "## email\n\n`client.app.login.email(email: string, request: string): object`\n\n**post** `/v1/app/login/email`\n\nSend a sign-in code to the user email address.\n\n### Parameters\n\n- `email: string`\n Email address to send the sign-in code to.\n\n- `request: string`\n Login request ID returned by the start step.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.rooms.events.retrieve', + method: 'client.app.login.email', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst event = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', {\n roomId: '!636q39766251:matrix.org',\n});\n\nconsole.log(event.event_id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);", }, python: { - method: 'matrix.rooms.events.retrieve', + method: 'app.login.email', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nevent = client.matrix.rooms.events.retrieve(\n event_id="$asfDuShaf7Gafaw:matrix.org",\n room_id="!636q39766251:matrix.org",\n)\nprint(event.event_id)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.email(\n email="dev@stainless.com",\n request="request",\n)\nprint(response)', }, go: { - method: 'client.Matrix.Rooms.Events.Get', + method: 'client.App.Login.Email', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tevent, err := client.Matrix.Rooms.Events.Get(\n\t\tcontext.TODO(),\n\t\t"$asfDuShaf7Gafaw:matrix.org",\n\t\tbeeperdesktopapi.MatrixRoomEventGetParams{\n\t\t\tRoomID: "!636q39766251:matrix.org",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", event.EventID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Email(context.TODO(), beeperdesktopapi.AppLoginEmailParams{\n\t\tEmail: "dev@stainless.com",\n\t\tRequest: "request",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'events retrieve', + method: 'login email', example: - "beeper-desktop-cli matrix:rooms:events retrieve \\\n --access-token 'My Access Token' \\\n --room-id '!636q39766251:matrix.org' \\\n --event-id '$asfDuShaf7Gafaw:matrix.org'", + "beeper-desktop app:login email \\\n --access-token 'My Access Token' \\\n --email dev@stainless.com \\\n --request request", }, php: { - method: 'matrix->rooms->events->retrieve', + method: 'app->login->email', example: - "matrix->rooms->events->retrieve(\n '$asfDuShaf7Gafaw:matrix.org', roomID: '!636q39766251:matrix.org'\n);\n\nvar_dump($event);", + "app->login->email(\n email: 'dev@stainless.com', request: 'request'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/v3/rooms/$ROOM_ID/event/$EVENT_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/email \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "email": "dev@stainless.com",\n "request": "request"\n }\'', }, }, }, { - name: 'whoami', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami', - httpMethod: 'get', - summary: 'Get info about the bridge and your logins.', + name: 'response', + endpoint: '/v1/app/login/response', + httpMethod: 'post', + summary: 'Complete login with code', description: - 'Get all info that is useful for presenting this bridge in a manager interface.\n* Server details: remote network details, available login flows, homeserver name, bridge bot user ID, command prefix\n* User details: management room ID, list of logins with current state and info\n', - stainlessPath: '(resource) matrix.bridges.auth > (method) whoami', - qualified: 'client.matrix.bridges.auth.whoami', - params: ['bridgeID: string;'], + 'Finish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.', + stainlessPath: '(resource) app.login > (method) response', + qualified: 'client.app.login.response', + params: ['request: string;', 'response: string;'], response: - "{ bridge_bot: string; command_prefix: string; homeserver: string; login_flows: { id: string; description: string; name: string; }[]; logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]; network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }; management_room?: string; }", + "{ desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }", markdown: - "## whoami\n\n`client.matrix.bridges.auth.whoami(bridgeID: string): { bridge_bot: string; command_prefix: string; homeserver: string; login_flows: object[]; logins: object[]; network: object; management_room?: string; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami`\n\nGet all info that is useful for presenting this bridge in a manager interface.\n* Server details: remote network details, available login flows, homeserver name, bridge bot user ID, command prefix\n* User details: management room ID, list of logins with current state and info\n\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ bridge_bot: string; command_prefix: string; homeserver: string; login_flows: { id: string; description: string; name: string; }[]; logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]; network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }; management_room?: string; }`\n Info about the bridge and user\n\n - `bridge_bot: string`\n - `command_prefix: string`\n - `homeserver: string`\n - `login_flows: { id: string; description: string; name: string; }[]`\n - `logins: { id: string; name: string; profile: { avatar?: string; email?: string; name?: string; phone?: string; username?: string; }; state: { state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; timestamp: number; error?: string; info?: object; message?: string; reason?: string; }; space_room?: string; }[]`\n - `network: { beeper_bridge_type: string; displayname: string; network_icon: string; network_id: string; network_url: string; }`\n - `management_room?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.whoami('bridgeID');\n\nconsole.log(response);\n```", + "## response\n\n`client.app.login.response(request: string, response: string): { desktopAPI: object; matrix: object; session: object; } | { copy: object; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n**post** `/v1/app/login/response`\n\nFinish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.\n\n### Parameters\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `response: string`\n Sign-in code from the user email.\n\n### Returns\n\n- `{ desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.whoami', + method: 'client.app.login.response', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.whoami('bridgeID');\n\nconsole.log(response.bridge_bot);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);", }, python: { - method: 'matrix.bridges.auth.whoami', + method: 'app.login.response', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.whoami(\n "bridgeID",\n)\nprint(response.bridge_bot)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.response(\n request="request",\n response="response",\n)\nprint(response)', }, go: { - method: 'client.Matrix.Bridges.Auth.Whoami', + method: 'client.App.Login.Response', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.Whoami(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.BridgeBot)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Response(context.TODO(), beeperdesktopapi.AppLoginResponseParams{\n\t\tRequest: "request",\n\t\tResponse: "response",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', }, cli: { - method: 'auth whoami', + method: 'login response', example: - "beeper-desktop-cli matrix:bridges:auth whoami \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop app:login response \\\n --access-token 'My Access Token' \\\n --request request \\\n --response response", }, php: { - method: 'matrix->bridges->auth->whoami', + method: 'app->login->response', example: - "matrix->bridges->auth->whoami('bridgeID');\n\nvar_dump($response);", + "app->login->response(\n request: 'request', response: 'response'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/whoami \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/response \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "request": "request",\n "response": "response"\n }\'', }, }, }, { - name: 'list_flows', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows', - httpMethod: 'get', - summary: 'Get the available login flows.', - description: 'Get the available login flows.', - stainlessPath: '(resource) matrix.bridges.auth > (method) list_flows', - qualified: 'client.matrix.bridges.auth.listFlows', - params: ['bridgeID: string;'], - response: '{ flows?: { id: string; description: string; name: string; }[]; }', + name: 'register', + endpoint: '/v1/app/login/register', + httpMethod: 'post', + summary: 'Create account', + description: 'Create a Beeper account after the user chooses a username and accepts the Terms of Use.', + stainlessPath: '(resource) app.login > (method) register', + qualified: 'client.app.login.register', + params: ['acceptTerms: true;', 'leadToken: string;', 'request: string;', 'username: string;'], + response: + "{ desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", markdown: - "## list_flows\n\n`client.matrix.bridges.auth.listFlows(bridgeID: string): { flows?: object[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows`\n\nGet the available login flows.\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ flows?: { id: string; description: string; name: string; }[]; }`\n\n - `flows?: { id: string; description: string; name: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.listFlows('bridgeID');\n\nconsole.log(response);\n```", + "## register\n\n`client.app.login.register(acceptTerms: true, leadToken: string, request: string, username: string): { desktopAPI: object; matrix: object; session: object; }`\n\n**post** `/v1/app/login/register`\n\nCreate a Beeper account after the user chooses a username and accepts the Terms of Use.\n\n### Parameters\n\n- `acceptTerms: true`\n Confirms that the user accepted the Terms of Use and acknowledged the Privacy Policy.\n\n- `leadToken: string`\n Registration token returned by Beeper.\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `username: string`\n Username selected by the user.\n\n### Returns\n\n- `{ desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }`\n - `matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }`\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.listFlows', + method: 'client.app.login.register', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.listFlows('bridgeID');\n\nconsole.log(response.flows);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response.desktopAPI);", }, python: { - method: 'matrix.bridges.auth.list_flows', + method: 'app.login.register', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.list_flows(\n "bridgeID",\n)\nprint(response.flows)', + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.register(\n accept_terms=True,\n lead_token="leadToken",\n request="request",\n username="x",\n)\nprint(response.desktop_api)', }, go: { - method: 'client.Matrix.Bridges.Auth.ListFlows', + method: 'client.App.Login.Register', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.ListFlows(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Flows)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Register(context.TODO(), beeperdesktopapi.AppLoginRegisterParams{\n\t\tAcceptTerms: true,\n\t\tLeadToken: "leadToken",\n\t\tRequest: "request",\n\t\tUsername: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.DesktopAPI)\n}\n', }, cli: { - method: 'auth list_flows', + method: 'login register', example: - "beeper-desktop-cli matrix:bridges:auth list-flows \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop app:login register \\\n --access-token 'My Access Token' \\\n --accept-terms true \\\n --lead-token leadToken \\\n --request request \\\n --username x", }, php: { - method: 'matrix->bridges->auth->listFlows', + method: 'app->login->register', example: - "matrix->bridges->auth->listFlows('bridgeID');\n\nvar_dump($response);", + "app->login->register(\n acceptTerms: true, leadToken: 'leadToken', request: 'request', username: 'x'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/flows \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/register \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "acceptTerms": true,\n "leadToken": "leadToken",\n "request": "request",\n "username": "x"\n }\'', }, }, }, { - name: 'list_logins', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins', - httpMethod: 'get', - summary: 'Get the login IDs of the current user.', - description: 'Get the login IDs of the current user.', - stainlessPath: '(resource) matrix.bridges.auth > (method) list_logins', - qualified: 'client.matrix.bridges.auth.listLogins', - params: ['bridgeID: string;'], - response: '{ login_ids?: string[]; }', + name: 'verify', + endpoint: '/v1/app/login/verification/recovery-key', + httpMethod: 'post', + summary: 'Verify with recovery key', + description: 'Unlock encrypted messages with the user recovery key.', + stainlessPath: '(resource) app.login.verification.recovery_key > (method) verify', + qualified: 'client.app.login.verification.recoveryKey.verify', + params: ['recoveryKey: string;'], + response: + "{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", markdown: - "## list_logins\n\n`client.matrix.bridges.auth.listLogins(bridgeID: string): { login_ids?: string[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins`\n\nGet the login IDs of the current user.\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `{ login_ids?: string[]; }`\n\n - `login_ids?: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.listLogins('bridgeID');\n\nconsole.log(response);\n```", + "## verify\n\n`client.app.login.verification.recoveryKey.verify(recoveryKey: string): { session: object; }`\n\n**post** `/v1/app/login/verification/recovery-key`\n\nUnlock encrypted messages with the user recovery key.\n\n### Parameters\n\n- `recoveryKey: string`\n Recovery key saved by the user.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.listLogins', + method: 'client.app.login.verification.recoveryKey.verify', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.listLogins('bridgeID');\n\nconsole.log(response.login_ids);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' });\n\nconsole.log(response.session);", }, python: { - method: 'matrix.bridges.auth.list_logins', + method: 'app.login.verification.recovery_key.verify', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.list_logins(\n "bridgeID",\n)\nprint(response.login_ids)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.login.verification.recovery_key.verify(\n recovery_key="x",\n)\nprint(response.session)', }, go: { - method: 'client.Matrix.Bridges.Auth.ListLogins', + method: 'client.App.Login.Verification.RecoveryKey.Verify', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.ListLogins(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.LoginIDs)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Verification.RecoveryKey.Verify(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyVerifyParams{\n\t\tRecoveryKey: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', }, cli: { - method: 'auth list_logins', + method: 'recovery_key verify', example: - "beeper-desktop-cli matrix:bridges:auth list-logins \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop app:login:verification:recovery-key verify \\\n --access-token 'My Access Token' \\\n --recovery-key x", }, php: { - method: 'matrix->bridges->auth->listLogins', + method: 'app->login->verification->recoveryKey->verify', example: - "matrix->bridges->auth->listLogins('bridgeID');\n\nvar_dump($response);", + "app->login->verification->recoveryKey->verify(\n recoveryKey: 'x'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/logins \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/verification/recovery-key \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryKey": "x"\n }\'', }, }, }, { - name: 'start_login', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}', + name: 'create', + endpoint: '/v1/app/login/verification/recovery-key/reset', httpMethod: 'post', - summary: 'Start a new login process.', - description: - "This endpoint starts a new login process, which is used to log into the bridge.\n\nThe basic flow of the entire login, including calling this endpoint, is:\n1. Call `GET /v3/login/flows` to get the list of available flows.\n If there's more than one flow, ask the user to pick which one they want to use.\n2. Call this endpoint with the chosen flow ID to start the login.\n The first login step will be returned.\n3. Render the information provided in the step.\n4. Call the `/login/step/...` endpoint corresponding to the step type:\n * For `user_input` and `cookies`, acquire the requested fields before calling the endpoint.\n * For `display_and_wait`, call the endpoint immediately\n (as there's nothing to acquire on the client side).\n5. Handle the data returned by the login step endpoint:\n * If an error is returned, the login has failed and must be restarted\n (from either step 1 or step 2) if the user wants to try again.\n * If step type `complete` is returned, the login finished successfully.\n * Otherwise, go to step 3 with the new data.\n", - stainlessPath: '(resource) matrix.bridges.auth > (method) start_login', - qualified: 'client.matrix.bridges.auth.startLogin', - params: ['bridgeID: string;', 'flowID: string;', 'login_id?: string;'], + summary: 'Create new recovery key', + description: 'Create a new recovery key when the user cannot use the existing one.', + stainlessPath: '(resource) app.login.verification.recovery_key.reset > (method) create', + qualified: 'client.app.login.verification.recoveryKey.reset.create', + params: ['existingRecoveryKey?: string;'], response: - "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + "{ recoveryKey: string; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", markdown: - "## start_login\n\n`client.matrix.bridges.auth.startLogin(bridgeID: string, flowID: string, login_id?: string): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}`\n\nThis endpoint starts a new login process, which is used to log into the bridge.\n\nThe basic flow of the entire login, including calling this endpoint, is:\n1. Call `GET /v3/login/flows` to get the list of available flows.\n If there's more than one flow, ask the user to pick which one they want to use.\n2. Call this endpoint with the chosen flow ID to start the login.\n The first login step will be returned.\n3. Render the information provided in the step.\n4. Call the `/login/step/...` endpoint corresponding to the step type:\n * For `user_input` and `cookies`, acquire the requested fields before calling the endpoint.\n * For `display_and_wait`, call the endpoint immediately\n (as there's nothing to acquire on the client side).\n5. Handle the data returned by the login step endpoint:\n * If an error is returned, the login has failed and must be restarted\n (from either step 1 or step 2) if the user wants to try again.\n * If step type `complete` is returned, the login finished successfully.\n * Otherwise, go to step 3 with the new data.\n\n\n### Parameters\n\n- `bridgeID: string`\n\n- `flowID: string`\n\n- `login_id?: string`\n An existing login ID to re-login as. If this is specified and the user logs into a different account, the provided ID will be logged out.\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## create\n\n`client.app.login.verification.recoveryKey.reset.create(existingRecoveryKey?: string): { recoveryKey: string; session: object; }`\n\n**post** `/v1/app/login/verification/recovery-key/reset`\n\nCreate a new recovery key when the user cannot use the existing one.\n\n### Parameters\n\n- `existingRecoveryKey?: string`\n Existing recovery key, if the user has it.\n\n### Returns\n\n- `{ recoveryKey: string; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `recoveryKey: string`\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reset = await client.app.login.verification.recoveryKey.reset.create();\n\nconsole.log(reset);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.startLogin', + method: 'client.app.login.verification.recoveryKey.reset.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' });\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reset = await client.app.login.verification.recoveryKey.reset.create();\n\nconsole.log(reset.recoveryKey);", }, python: { - method: 'matrix.bridges.auth.start_login', + method: 'app.login.verification.recovery_key.reset.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.start_login(\n flow_id="qr",\n bridge_id="bridgeID",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreset = client.app.login.verification.recovery_key.reset.create()\nprint(reset.recovery_key)', }, go: { - method: 'client.Matrix.Bridges.Auth.StartLogin', + method: 'client.App.Login.Verification.RecoveryKey.Reset.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.StartLogin(\n\t\tcontext.TODO(),\n\t\t"qr",\n\t\tbeeperdesktopapi.MatrixBridgeAuthStartLoginParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treset, err := client.App.Login.Verification.RecoveryKey.Reset.New(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyResetNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reset.RecoveryKey)\n}\n', }, cli: { - method: 'auth start_login', + method: 'reset create', example: - "beeper-desktop-cli matrix:bridges:auth start-login \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --flow-id qr", + "beeper-desktop app:login:verification:recovery-key:reset create \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->bridges->auth->startLogin', + method: 'app->login->verification->recoveryKey->reset->create', example: - "matrix->bridges->auth->startLogin(\n 'qr', bridgeID: 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496'\n);\n\nvar_dump($response);", + "app->login->verification->recoveryKey->reset->create(\n existingRecoveryKey: 'existingRecoveryKey'\n);\n\nvar_dump($reset);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/start/$FLOW_ID \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/login/verification/recovery-key/reset \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'submit_user_input', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input', + name: 'confirm', + endpoint: '/v1/app/login/verification/recovery-key/reset/confirm', httpMethod: 'post', - summary: 'Submit user input in a login process.', - description: 'Submit user input in a login process.', - stainlessPath: '(resource) matrix.bridges.auth > (method) submit_user_input', - qualified: 'client.matrix.bridges.auth.submitUserInput', - params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;', 'body: object;'], + summary: 'Confirm new recovery key', + description: 'Confirm that the new recovery key should be used for this account.', + stainlessPath: '(resource) app.login.verification.recovery_key.reset > (method) confirm', + qualified: 'client.app.login.verification.recoveryKey.reset.confirm', + params: ['recoveryKey: string;'], response: - "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + "{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", markdown: - "## submit_user_input\n\n`client.matrix.bridges.auth.submitUserInput(bridgeID: string, loginProcessID: string, stepID: string, body: object): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input`\n\nSubmit user input in a login process.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n- `body: object`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.submitUserInput('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);\n```", + "## confirm\n\n`client.app.login.verification.recoveryKey.reset.confirm(recoveryKey: string): { session: object; }`\n\n**post** `/v1/app/login/verification/recovery-key/reset/confirm`\n\nConfirm that the new recovery key should be used for this account.\n\n### Parameters\n\n- `recoveryKey: string`\n New recovery key returned by the reset step.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.submitUserInput', + method: 'client.app.login.verification.recoveryKey.reset.confirm', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.submitUserInput('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.login.verification.recoveryKey.reset.confirm({\n recoveryKey: 'x',\n});\n\nconsole.log(response.session);", }, python: { - method: 'matrix.bridges.auth.submit_user_input', + method: 'app.login.verification.recovery_key.reset.confirm', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.submit_user_input(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n body={\n "foo": "string"\n },\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.login.verification.recovery_key.reset.confirm(\n recovery_key="x",\n)\nprint(response.session)', }, go: { - method: 'client.Matrix.Bridges.Auth.SubmitUserInput', + method: 'client.App.Login.Verification.RecoveryKey.Reset.Confirm', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.SubmitUserInput(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthSubmitUserInputParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t\tBody: map[string]string{\n\t\t\t\t"foo": "string",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Verification.RecoveryKey.Reset.Confirm(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyResetConfirmParams{\n\t\tRecoveryKey: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', }, cli: { - method: 'auth submit_user_input', + method: 'reset confirm', example: - "beeper-desktop-cli matrix:bridges:auth submit-user-input \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID \\\n --body '{foo: string}'", + "beeper-desktop app:login:verification:recovery-key:reset confirm \\\n --access-token 'My Access Token' \\\n --recovery-key x", }, php: { - method: 'matrix->bridges->auth->submitUserInput', + method: 'app->login->verification->recoveryKey->reset->confirm', example: - "matrix->bridges->auth->submitUserInput(\n 'stepID',\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: ['foo' => 'string'],\n);\n\nvar_dump($response);", + "app->login->verification->recoveryKey->reset->confirm(\n recoveryKey: 'x'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/user_input \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "foo": "string"\n }\'', + 'curl http://localhost:23373/v1/app/login/verification/recovery-key/reset/confirm \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryKey": "x"\n }\'', }, }, }, { - name: 'submit_cookies', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies', - httpMethod: 'post', - summary: 'Submit extracted cookies in a login process.', - description: 'Submit extracted cookies in a login process.', - stainlessPath: '(resource) matrix.bridges.auth > (method) submit_cookies', - qualified: 'client.matrix.bridges.auth.submitCookies', - params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;', 'body: object;'], + name: 'list', + endpoint: '/v1/app/verifications', + httpMethod: 'get', + summary: 'List active verifications', + description: + 'List pending and active device verification transactions. Use this to recover state without a websocket connection.', + stainlessPath: '(resource) app.verifications > (method) list', + qualified: 'client.app.verifications.list', response: - "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + "{ items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]; }", markdown: - "## submit_cookies\n\n`client.matrix.bridges.auth.submitCookies(bridgeID: string, loginProcessID: string, stepID: string, body: object): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies`\n\nSubmit extracted cookies in a login process.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n- `body: object`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.submitCookies('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);\n```", + "## list\n\n`client.app.verifications.list(): { items: object[]; }`\n\n**get** `/v1/app/verifications`\n\nList pending and active device verification transactions. Use this to recover state without a websocket connection.\n\n### Returns\n\n- `{ items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]; }`\n\n - `items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verifications = await client.app.verifications.list();\n\nconsole.log(verifications);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.submitCookies', + method: 'client.app.verifications.list', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.submitCookies('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: { foo: 'string' },\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verifications = await client.app.verifications.list();\n\nconsole.log(verifications.items);", }, python: { - method: 'matrix.bridges.auth.submit_cookies', + method: 'app.verifications.list', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.submit_cookies(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n body={\n "foo": "string"\n },\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverifications = client.app.verifications.list()\nprint(verifications.items)', }, go: { - method: 'client.Matrix.Bridges.Auth.SubmitCookies', + method: 'client.App.Verifications.List', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.SubmitCookies(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthSubmitCookiesParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t\tBody: map[string]string{\n\t\t\t\t"foo": "string",\n\t\t\t},\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverifications, err := client.App.Verifications.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verifications.Items)\n}\n', }, cli: { - method: 'auth submit_cookies', - example: - "beeper-desktop-cli matrix:bridges:auth submit-cookies \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID \\\n --body '{foo: string}'", + method: 'verifications list', + example: "beeper-desktop app:verifications list \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->bridges->auth->submitCookies', + method: 'app->verifications->list', example: - "matrix->bridges->auth->submitCookies(\n 'stepID',\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n body: ['foo' => 'string'],\n);\n\nvar_dump($response);", + "app->verifications->list();\n\nvar_dump($verifications);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/cookies \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "foo": "string"\n }\'', + 'curl http://localhost:23373/v1/app/verifications \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'wait_for_step', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait', + name: 'create', + endpoint: '/v1/app/verifications', httpMethod: 'post', - summary: 'Wait for the next step after displaying data to the user.', - description: 'Wait for the next step after displaying data to the user.', - stainlessPath: '(resource) matrix.bridges.auth > (method) wait_for_step', - qualified: 'client.matrix.bridges.auth.waitForStep', - params: ['bridgeID: string;', 'loginProcessID: string;', 'stepID: string;'], + summary: 'Start device verification', + description: 'Start verifying this device from another signed-in device.', + stainlessPath: '(resource) app.verifications > (method) create', + qualified: 'client.app.verifications.create', + params: ["purpose?: 'login' | 'device';", 'userID?: string;'], response: - "{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }", + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", markdown: - "## wait_for_step\n\n`client.matrix.bridges.auth.waitForStep(bridgeID: string, loginProcessID: string, stepID: string): { display_and_wait: object; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: object; instructions?: string; login_id?: string; step_id?: string; } | { cookies: object; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: object; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait`\n\nWait for the next step after displaying data to the user.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginProcessID: string`\n\n- `stepID: string`\n\n### Returns\n\n- `{ display_and_wait: { type: 'qr' | 'emoji' | 'code' | 'nothing'; data?: string; image_url?: string; }; type: 'display_and_wait'; instructions?: string; login_id?: string; step_id?: string; } | { type: 'user_input'; user_input: { fields: { id: string; name: string; type: string; default_value?: string; description?: string; options?: string[]; pattern?: string; }[]; attachments?: { content: string; filename: string; type: 'm.image' | 'm.audio'; info?: object; }[]; }; instructions?: string; login_id?: string; step_id?: string; } | { cookies: { fields: { name: string; type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; cookie_domain?: string; request_url_regex?: string; }[]; url: string; extract_js?: string; user_agent?: string; wait_for_url_pattern?: string; }; type: 'cookies'; instructions?: string; login_id?: string; step_id?: string; } | { complete: { user_login_id?: string; }; type: 'complete'; instructions?: string; login_id?: string; step_id?: string; }`\n A step in a login process.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.waitForStep('stepID', { bridgeID: 'bridgeID', loginProcessID: 'loginProcessID' });\n\nconsole.log(response);\n```", + "## create\n\n`client.app.verifications.create(purpose?: 'login' | 'device', userID?: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications`\n\nStart verifying this device from another signed-in device.\n\n### Parameters\n\n- `purpose?: 'login' | 'device'`\n Why this verification is being started.\n\n- `userID?: string`\n User ID to verify. Defaults to the signed-in user.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.verifications.create();\n\nconsole.log(verification);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.waitForStep', + method: 'client.app.verifications.create', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.waitForStep('stepID', {\n bridgeID: 'bridgeID',\n loginProcessID: 'loginProcessID',\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.verifications.create();\n\nconsole.log(verification.session);", }, python: { - method: 'matrix.bridges.auth.wait_for_step', + method: 'app.verifications.create', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.wait_for_step(\n step_id="stepID",\n bridge_id="bridgeID",\n login_process_id="loginProcessID",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.verifications.create()\nprint(verification.session)', }, go: { - method: 'client.Matrix.Bridges.Auth.WaitForStep', + method: 'client.App.Verifications.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.WaitForStep(\n\t\tcontext.TODO(),\n\t\t"stepID",\n\t\tbeeperdesktopapi.MatrixBridgeAuthWaitForStepParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t\tLoginProcessID: "loginProcessID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.Verifications.New(context.TODO(), beeperdesktopapi.AppVerificationNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.Session)\n}\n', }, cli: { - method: 'auth wait_for_step', - example: - "beeper-desktop-cli matrix:bridges:auth wait-for-step \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-process-id loginProcessID \\\n --step-id stepID", + method: 'verifications create', + example: "beeper-desktop app:verifications create \\\n --access-token 'My Access Token'", }, php: { - method: 'matrix->bridges->auth->waitForStep', + method: 'app->verifications->create', example: - "matrix->bridges->auth->waitForStep(\n 'stepID', bridgeID: 'bridgeID', loginProcessID: 'loginProcessID'\n);\n\nvar_dump($response);", + "app->verifications->create(\n purpose: 'login', userID: 'userID'\n);\n\nvar_dump($verification);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/login/step/$LOGIN_PROCESS_ID/$STEP_ID/display_and_wait \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/verifications \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'logout', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}', - httpMethod: 'post', - summary: 'Log out of an existing login.', - description: 'Log out of an existing login.', - stainlessPath: '(resource) matrix.bridges.auth > (method) logout', - qualified: 'client.matrix.bridges.auth.logout', - params: ['bridgeID: string;', 'loginID: string;'], - response: 'object', + name: 'retrieve', + endpoint: '/v1/app/verifications/{verificationID}', + httpMethod: 'get', + summary: 'Get verification', + description: 'Get the current state of a device verification transaction.', + stainlessPath: '(resource) app.verifications > (method) retrieve', + qualified: 'client.app.verifications.retrieve', + params: ['verificationID: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", markdown: - "## logout\n\n`client.matrix.bridges.auth.logout(bridgeID: string, loginID: string): object`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}`\n\nLog out of an existing login.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `loginID: string`\n The unique ID of a login. Defined by the network connector.\n\n### Returns\n\n- `object`\n Empty object\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## retrieve\n\n`client.app.verifications.retrieve(verificationID: string): { session: object; verification?: object; }`\n\n**get** `/v1/app/verifications/{verificationID}`\n\nGet the current state of a device verification transaction.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.verifications.retrieve('x');\n\nconsole.log(verification);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.auth.logout', + method: 'client.app.verifications.retrieve', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', {\n bridgeID: 'bridgeID',\n});\n\nconsole.log(response);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.verifications.retrieve('x');\n\nconsole.log(verification.session);", }, python: { - method: 'matrix.bridges.auth.logout', + method: 'app.verifications.retrieve', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.auth.logout(\n login_id="bcc68892-b180-414f-9516-b4aadf7d0496",\n bridge_id="bridgeID",\n)\nprint(response)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.verifications.retrieve(\n "x",\n)\nprint(verification.session)', }, go: { - method: 'client.Matrix.Bridges.Auth.Logout', + method: 'client.App.Verifications.Get', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Auth.Logout(\n\t\tcontext.TODO(),\n\t\t"bcc68892-b180-414f-9516-b4aadf7d0496",\n\t\tbeeperdesktopapi.MatrixBridgeAuthLogoutParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.Verifications.Get(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.Session)\n}\n', }, cli: { - method: 'auth logout', + method: 'verifications retrieve', example: - "beeper-desktop-cli matrix:bridges:auth logout \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --login-id bcc68892-b180-414f-9516-b4aadf7d0496", + "beeper-desktop app:verifications retrieve \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->auth->logout', + method: 'app->verifications->retrieve', example: - "matrix->bridges->auth->logout(\n 'bcc68892-b180-414f-9516-b4aadf7d0496', bridgeID: 'bridgeID'\n);\n\nvar_dump($response);", + "app->verifications->retrieve('x');\n\nvar_dump($verification);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/logout/$LOGIN_ID \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'list', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts', - httpMethod: 'get', - summary: 'Get a list of contacts.', - description: 'Get a list of contacts.', - stainlessPath: '(resource) matrix.bridges.contacts > (method) list', - qualified: 'client.matrix.bridges.contacts.list', - params: ['bridgeID: string;', 'login_id?: string;'], + name: 'accept', + endpoint: '/v1/app/verifications/{verificationID}/accept', + httpMethod: 'post', + summary: 'Accept device verification', + description: 'Accept an incoming device verification request.', + stainlessPath: '(resource) app.verifications > (method) accept', + qualified: 'client.app.verifications.accept', + params: ['verificationID: string;'], response: - '{ contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }', + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", markdown: - "## list\n\n`client.matrix.bridges.contacts.list(bridgeID: string, login_id?: string): { contacts?: object[]; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts`\n\nGet a list of contacts.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }`\n\n - `contacts?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst contacts = await client.matrix.bridges.contacts.list('bridgeID');\n\nconsole.log(contacts);\n```", + "## accept\n\n`client.app.verifications.accept(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/accept`\n\nAccept an incoming device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.accept('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.contacts.list', + method: 'client.app.verifications.accept', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst contacts = await client.matrix.bridges.contacts.list('bridgeID');\n\nconsole.log(contacts.contacts);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.accept('x');\n\nconsole.log(response.session);", }, python: { - method: 'matrix.bridges.contacts.list', + method: 'app.verifications.accept', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\ncontacts = client.matrix.bridges.contacts.list(\n bridge_id="bridgeID",\n)\nprint(contacts.contacts)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.accept(\n "x",\n)\nprint(response.session)', }, go: { - method: 'client.Matrix.Bridges.Contacts.List', + method: 'client.App.Verifications.Accept', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tcontacts, err := client.Matrix.Bridges.Contacts.List(\n\t\tcontext.TODO(),\n\t\t"bridgeID",\n\t\tbeeperdesktopapi.MatrixBridgeContactListParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", contacts.Contacts)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Accept(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', }, cli: { - method: 'contacts list', + method: 'verifications accept', example: - "beeper-desktop-cli matrix:bridges:contacts list \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop app:verifications accept \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->contacts->list', + method: 'app->verifications->accept', example: - "matrix->bridges->contacts->list(\n 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496'\n);\n\nvar_dump($contacts);", + "app->verifications->accept('x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/contacts \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/accept \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'search', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users', + name: 'cancel', + endpoint: '/v1/app/verifications/{verificationID}/cancel', httpMethod: 'post', - summary: 'Search for users on the remote network', - description: 'Search for users on the remote network', - stainlessPath: '(resource) matrix.bridges.users > (method) search', - qualified: 'client.matrix.bridges.users.search', - params: ['bridgeID: string;', 'login_id?: string;', 'query?: string;'], + summary: 'Cancel device verification', + description: 'Cancel an active device verification request.', + stainlessPath: '(resource) app.verifications > (method) cancel', + qualified: 'client.app.verifications.cancel', + params: ['verificationID: string;', 'code?: string;', 'reason?: string;'], response: - '{ results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }', + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", markdown: - "## search\n\n`client.matrix.bridges.users.search(bridgeID: string, login_id?: string, query?: string): { results?: object[]; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users`\n\nSearch for users on the remote network\n\n### Parameters\n\n- `bridgeID: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n- `query?: string`\n The search query to send to the remote network\n\n### Returns\n\n- `{ results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]; }`\n\n - `results?: { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.users.search('bridgeID');\n\nconsole.log(response);\n```", + "## cancel\n\n`client.app.verifications.cancel(verificationID: string, code?: string, reason?: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/cancel`\n\nCancel an active device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n- `code?: string`\n Optional cancellation code.\n\n- `reason?: string`\n Optional user-facing cancellation reason.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.cancel('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.users.search', + method: 'client.app.verifications.cancel', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.users.search('bridgeID');\n\nconsole.log(response.results);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.cancel('x');\n\nconsole.log(response.session);", }, python: { - method: 'matrix.bridges.users.search', + method: 'app.verifications.cancel', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.users.search(\n bridge_id="bridgeID",\n)\nprint(response.results)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.cancel(\n verification_id="x",\n)\nprint(response.session)', }, go: { - method: 'client.Matrix.Bridges.Users.Search', + method: 'client.App.Verifications.Cancel', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Users.Search(\n\t\tcontext.TODO(),\n\t\t"bridgeID",\n\t\tbeeperdesktopapi.MatrixBridgeUserSearchParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Results)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Cancel(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.AppVerificationCancelParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', }, cli: { - method: 'users search', + method: 'verifications cancel', example: - "beeper-desktop-cli matrix:bridges:users search \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop app:verifications cancel \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->users->search', + method: 'app->verifications->cancel', example: - "matrix->bridges->users->search(\n 'bridgeID', loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496', query: 'query'\n);\n\nvar_dump($response);", + "app->verifications->cancel(\n 'x', code: 'code', reason: 'reason'\n);\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/search_users \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/cancel \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'resolve', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}', - httpMethod: 'get', - summary: 'Resolve an identifier to a user on the remote network.', - description: 'Resolve an identifier to a user on the remote network.', - stainlessPath: '(resource) matrix.bridges.users > (method) resolve', - qualified: 'client.matrix.bridges.users.resolve', - params: ['bridgeID: string;', 'identifier: string;', 'login_id?: string;'], + name: 'scan', + endpoint: '/v1/app/verifications/qr/scan', + httpMethod: 'post', + summary: 'Scan verification QR code', + description: 'Submit the QR code scanned from another signed-in device.', + stainlessPath: '(resource) app.verifications.qr > (method) scan', + qualified: 'client.app.verifications.qr.scan', + params: ['data: string;'], response: - '{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }', + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", markdown: - "## resolve\n\n`client.matrix.bridges.users.resolve(bridgeID: string, identifier: string, login_id?: string): { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}`\n\nResolve an identifier to a user on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `identifier: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n A successfully resolved identifier.\n\n - `id: string`\n - `avatar_url?: string`\n - `dm_room_mxid?: string`\n - `identifiers?: string[]`\n - `mxid?: string`\n - `name?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## scan\n\n`client.app.verifications.qr.scan(data: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/qr/scan`\n\nSubmit the QR code scanned from another signed-in device.\n\n### Parameters\n\n- `data: string`\n QR code payload scanned from the other device.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.qr.scan({ data: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.users.resolve', + method: 'client.app.verifications.qr.scan', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.qr.scan({ data: 'x' });\n\nconsole.log(response.session);", }, python: { - method: 'matrix.bridges.users.resolve', + method: 'app.verifications.qr.scan', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.users.resolve(\n identifier="identifier",\n bridge_id="bridgeID",\n)\nprint(response.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.qr.scan(\n data="x",\n)\nprint(response.session)', }, go: { - method: 'client.Matrix.Bridges.Users.Resolve', + method: 'client.App.Verifications.Qr.Scan', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Users.Resolve(\n\t\tcontext.TODO(),\n\t\t"identifier",\n\t\tbeeperdesktopapi.MatrixBridgeUserResolveParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Qr.Scan(context.TODO(), beeperdesktopapi.AppVerificationQrScanParams{\n\t\tData: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', }, cli: { - method: 'users resolve', + method: 'qr scan', example: - "beeper-desktop-cli matrix:bridges:users resolve \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --identifier identifier", + "beeper-desktop app:verifications:qr scan \\\n --access-token 'My Access Token' \\\n --data x", }, php: { - method: 'matrix->bridges->users->resolve', + method: 'app->verifications->qr->scan', example: - "matrix->bridges->users->resolve(\n 'identifier',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n);\n\nvar_dump($response);", + "app->verifications->qr->scan(data: 'x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/resolve_identifier/$IDENTIFIER \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/verifications/qr/scan \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "data": "x"\n }\'', }, }, }, { - name: 'create_dm', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}', + name: 'confirm_scanned', + endpoint: '/v1/app/verifications/{verificationID}/qr/confirm-scanned', httpMethod: 'post', - summary: 'Create a direct chat with a user on the remote network.', - description: 'Create a direct chat with a user on the remote network.', - stainlessPath: '(resource) matrix.bridges.rooms > (method) create_dm', - qualified: 'client.matrix.bridges.rooms.createDm', - params: ['bridgeID: string;', 'identifier: string;', 'login_id?: string;'], + summary: 'Confirm QR code scan', + description: 'Confirm that another device scanned this device QR code.', + stainlessPath: '(resource) app.verifications.qr > (method) confirm_scanned', + qualified: 'client.app.verifications.qr.confirmScanned', + params: ['verificationID: string;'], response: - '{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }', + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", markdown: - "## create_dm\n\n`client.matrix.bridges.rooms.createDm(bridgeID: string, identifier: string, login_id?: string): { id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}`\n\nCreate a direct chat with a user on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `identifier: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n### Returns\n\n- `{ id: string; avatar_url?: string; dm_room_mxid?: string; identifiers?: string[]; mxid?: string; name?: string; }`\n A successfully resolved identifier.\n\n - `id: string`\n - `avatar_url?: string`\n - `dm_room_mxid?: string`\n - `identifiers?: string[]`\n - `mxid?: string`\n - `name?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## confirm_scanned\n\n`client.app.verifications.qr.confirmScanned(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/qr/confirm-scanned`\n\nConfirm that another device scanned this device QR code.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.qr.confirmScanned('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.rooms.createDm', + method: 'client.app.verifications.qr.confirmScanned', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' });\n\nconsole.log(response.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.qr.confirmScanned('x');\n\nconsole.log(response.session);", }, python: { - method: 'matrix.bridges.rooms.create_dm', + method: 'app.verifications.qr.confirm_scanned', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.rooms.create_dm(\n identifier="identifier",\n bridge_id="bridgeID",\n)\nprint(response.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.qr.confirm_scanned(\n "x",\n)\nprint(response.session)', }, go: { - method: 'client.Matrix.Bridges.Rooms.NewDm', + method: 'client.App.Verifications.Qr.ConfirmScanned', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Rooms.NewDm(\n\t\tcontext.TODO(),\n\t\t"identifier",\n\t\tbeeperdesktopapi.MatrixBridgeRoomNewDmParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Qr.ConfirmScanned(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', }, cli: { - method: 'rooms create_dm', + method: 'qr confirm_scanned', example: - "beeper-desktop-cli matrix:bridges:rooms create-dm \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --identifier identifier", + "beeper-desktop app:verifications:qr confirm-scanned \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->rooms->createDm', + method: 'app->verifications->qr->confirmScanned', example: - "matrix->bridges->rooms->createDm(\n 'identifier',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n);\n\nvar_dump($response);", + "app->verifications->qr->confirmScanned('x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/create_dm/$IDENTIFIER \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/qr/confirm-scanned \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'create_group', - endpoint: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}', + name: 'start', + endpoint: '/v1/app/verifications/{verificationID}/sas/start', httpMethod: 'post', - summary: 'Create a group chat on the remote network.', - description: 'Create a group chat on the remote network.', - stainlessPath: '(resource) matrix.bridges.rooms > (method) create_group', - qualified: 'client.matrix.bridges.rooms.createGroup', - params: [ - 'bridgeID: string;', - 'groupType: string;', - 'login_id?: string;', - 'avatar?: { url?: string; };', - 'disappear?: { timer?: number; type?: string; };', - 'name?: { name?: string; };', - 'parent?: object;', - 'participants?: string[];', - 'room_id?: string;', - 'topic?: { topic?: string; };', - 'type?: string;', - 'username?: string;', - ], - response: '{ id: string; mxid: string; }', + summary: 'Start emoji verification', + description: 'Start emoji comparison for device verification.', + stainlessPath: '(resource) app.verifications.sas > (method) start', + qualified: 'client.app.verifications.sas.start', + params: ['verificationID: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", markdown: - "## create_group\n\n`client.matrix.bridges.rooms.createGroup(bridgeID: string, groupType: string, login_id?: string, avatar?: { url?: string; }, disappear?: { timer?: number; type?: string; }, name?: { name?: string; }, parent?: object, participants?: string[], room_id?: string, topic?: { topic?: string; }, type?: string, username?: string): { id: string; mxid: string; }`\n\n**post** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}`\n\nCreate a group chat on the remote network.\n\n### Parameters\n\n- `bridgeID: string`\n\n- `groupType: string`\n\n- `login_id?: string`\n An optional explicit login ID to do the action through.\n\n- `avatar?: { url?: string; }`\n The `m.room.avatar` event content for the room.\n - `url?: string`\n\n- `disappear?: { timer?: number; type?: string; }`\n The `com.beeper.disappearing_timer` event content for the room.\n - `timer?: number`\n - `type?: string`\n\n- `name?: { name?: string; }`\n The `m.room.name` event content for the room.\n - `name?: string`\n\n- `parent?: object`\n\n- `participants?: string[]`\n The users to add to the group initially.\n\n- `room_id?: string`\n An existing Matrix room ID to bridge to.\nThe other parameters must be already in sync with the room state when using this parameter.\n\n\n- `topic?: { topic?: string; }`\n The `m.room.topic` event content for the room.\n - `topic?: string`\n\n- `type?: string`\n The type of group to create.\n\n- `username?: string`\n The public username for the created group.\n\n### Returns\n\n- `{ id: string; mxid: string; }`\n A successfully created group chat.\n\n - `id: string`\n - `mxid: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.matrix.bridges.rooms.createGroup('groupType', { bridgeID: 'bridgeID' });\n\nconsole.log(response);\n```", + "## start\n\n`client.app.verifications.sas.start(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/sas/start`\n\nStart emoji comparison for device verification.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.sas.start('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.rooms.createGroup', + method: 'client.app.verifications.sas.start', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.matrix.bridges.rooms.createGroup('groupType', {\n bridgeID: 'bridgeID',\n});\n\nconsole.log(response.id);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.sas.start('x');\n\nconsole.log(response.session);", }, python: { - method: 'matrix.bridges.rooms.create_group', + method: 'app.verifications.sas.start', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.matrix.bridges.rooms.create_group(\n group_type="groupType",\n bridge_id="bridgeID",\n)\nprint(response.id)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.sas.start(\n "x",\n)\nprint(response.session)', }, go: { - method: 'client.Matrix.Bridges.Rooms.NewGroup', + method: 'client.App.Verifications.SAS.Start', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.Matrix.Bridges.Rooms.NewGroup(\n\t\tcontext.TODO(),\n\t\t"groupType",\n\t\tbeeperdesktopapi.MatrixBridgeRoomNewGroupParams{\n\t\t\tBridgeID: "bridgeID",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.SAS.Start(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', }, cli: { - method: 'rooms create_group', + method: 'sas start', example: - "beeper-desktop-cli matrix:bridges:rooms create-group \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID \\\n --group-type groupType", + "beeper-desktop app:verifications:sas start \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->rooms->createGroup', + method: 'app->verifications->sas->start', example: - "matrix->bridges->rooms->createGroup(\n 'groupType',\n bridgeID: 'bridgeID',\n loginID: 'bcc68892-b180-414f-9516-b4aadf7d0496',\n avatar: ['url' => 'url'],\n disappear: ['timer' => 0, 'type' => 'type'],\n name: ['name' => 'name'],\n parent: (object) [],\n participants: ['string'],\n roomID: 'room_id',\n topic: ['topic' => 'topic'],\n type: 'channel',\n username: 'username',\n);\n\nvar_dump($response);", + "app->verifications->sas->start('x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/create_group/$GROUP_TYPE \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/sas/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, { - name: 'retrieve', - endpoint: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities', - httpMethod: 'get', - summary: 'Get bridge capabilities', - description: 'Get bridge capabilities', - stainlessPath: '(resource) matrix.bridges.capabilities > (method) retrieve', - qualified: 'client.matrix.bridges.capabilities.retrieve', - params: ['bridgeID: string;'], - response: 'object', + name: 'confirm', + endpoint: '/v1/app/verifications/{verificationID}/sas/confirm', + httpMethod: 'post', + summary: 'Confirm emoji verification', + description: 'Confirm that the emoji or number sequence matches on both devices.', + stainlessPath: '(resource) app.verifications.sas > (method) confirm', + qualified: 'client.app.verifications.sas.confirm', + params: ['verificationID: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", markdown: - "## retrieve\n\n`client.matrix.bridges.capabilities.retrieve(bridgeID: string): object`\n\n**get** `/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities`\n\nGet bridge capabilities\n\n### Parameters\n\n- `bridgeID: string`\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst capability = await client.matrix.bridges.capabilities.retrieve('bridgeID');\n\nconsole.log(capability);\n```", + "## confirm\n\n`client.app.verifications.sas.confirm(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/sas/confirm`\n\nConfirm that the emoji or number sequence matches on both devices.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.sas.confirm('x');\n\nconsole.log(response);\n```", perLanguage: { typescript: { - method: 'client.matrix.bridges.capabilities.retrieve', + method: 'client.app.verifications.sas.confirm', example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst capability = await client.matrix.bridges.capabilities.retrieve('bridgeID');\n\nconsole.log(capability);", + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.sas.confirm('x');\n\nconsole.log(response.session);", }, python: { - method: 'matrix.bridges.capabilities.retrieve', + method: 'app.verifications.sas.confirm', example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\ncapability = client.matrix.bridges.capabilities.retrieve(\n "bridgeID",\n)\nprint(capability)', + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.sas.confirm(\n "x",\n)\nprint(response.session)', }, go: { - method: 'client.Matrix.Bridges.Capabilities.Get', + method: 'client.App.Verifications.SAS.Confirm', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tcapability, err := client.Matrix.Bridges.Capabilities.Get(context.TODO(), "bridgeID")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", capability)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.SAS.Confirm(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', }, cli: { - method: 'capabilities retrieve', + method: 'sas confirm', example: - "beeper-desktop-cli matrix:bridges:capabilities retrieve \\\n --access-token 'My Access Token' \\\n --bridge-id bridgeID", + "beeper-desktop app:verifications:sas confirm \\\n --access-token 'My Access Token' \\\n --verification-id x", }, php: { - method: 'matrix->bridges->capabilities->retrieve', + method: 'app->verifications->sas->confirm', example: - "matrix->bridges->capabilities->retrieve('bridgeID');\n\nvar_dump($capability);", + "app->verifications->sas->confirm('x');\n\nvar_dump($response);", }, http: { example: - 'curl http://localhost:23373/_matrix/client/unstable/com.beeper.bridge/$BRIDGE_ID/_matrix/provision/v3/capabilities \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/sas/confirm \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', }, }, }, @@ -3382,7 +2770,7 @@ const EMBEDDED_READMES: { language: string; content: string }[] = [ { language: 'cli', content: - "# Beeper Desktop CLI\n\nThe official CLI for the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/).\n\n\n\n## Installation\n\n### Installing with Homebrew\n\n~~~sh\nbrew install beeper/tap/beeper-desktop-cli\n~~~\n\n### Installing with Go\n\nTo test or install the CLI locally, you need [Go](https://go.dev/doc/install) version 1.22 or later installed.\n\n~~~sh\ngo install 'github.com/beeper/desktop-api-cli/cmd/beeper-desktop-cli@latest'\n~~~\n\nOnce you have run `go install`, the binary is placed in your Go bin directory:\n\n- **Default location**: `$HOME/go/bin` (or `$GOPATH/bin` if GOPATH is set)\n- **Check your path**: Run `go env GOPATH` to see the base directory\n\nIf commands aren't found after installation, add the Go bin directory to your PATH:\n\n~~~sh\n# Add to your shell profile (.zshrc, .bashrc, etc.)\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n~~~\n\n\n\n### Running Locally\n\nAfter cloning the git repository for this project, you can use the\n`scripts/run` script to run the tool locally:\n\n~~~sh\n./scripts/run args...\n~~~\n\n## Usage\n\nThe CLI follows a resource-based command structure:\n\n~~~sh\nbeeper-desktop-cli [resource] [flags...]\n~~~\n\n~~~sh\nbeeper-desktop-cli chats search \\\n --access-token 'My Access Token' \\\n --account-id matrix \\\n --account-id discordgo \\\n --account-id local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --include-muted \\\n --limit 3 \\\n --type single\n~~~\n\nFor details about specific commands, use the `--help` flag.\n\n### Environment variables\n\n| Environment variable | Description | Required |\n| --------------------- | --------------------------------------------------------------------------------------------------------------- | -------- |\n| `BEEPER_ACCESS_TOKEN` | Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. | yes |\n\n### Global flags\n\n- `--access-token` - Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. (can also be set with `BEEPER_ACCESS_TOKEN` env var)\n- `--help` - Show command line usage\n- `--debug` - Enable debug logging (includes HTTP request/response details)\n- `--version`, `-v` - Show the CLI version\n- `--base-url` - Use a custom API backend URL\n- `--format` - Change the output format (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--format-error` - Change the output format for errors (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--transform` - Transform the data output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n- `--transform-error` - Transform the error output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n\n### Passing files as arguments\n\nTo pass files to your API, you can use the `@myfile.ext` syntax:\n\n~~~bash\nbeeper-desktop-cli --arg @abe.jpg\n~~~\n\nFiles can also be passed inside JSON or YAML blobs:\n\n~~~bash\nbeeper-desktop-cli --arg '{image: \"@abe.jpg\"}'\n# Equivalent:\nbeeper-desktop-cli < --username '\\@abe'\n~~~\n\n#### Explicit encoding\n\nFor JSON endpoints, the CLI tool does filetype sniffing to determine whether the\nfile contents should be sent as a string literal (for plain text files) or as a\nbase64-encoded string literal (for binary files). If you need to explicitly send\nthe file as either plain text or base64-encoded data, you can use\n`@file://myfile.txt` (for string encoding) or `@data://myfile.dat` (for\nbase64-encoding). Note that absolute paths will begin with `@file://` or\n`@data://`, followed by a third `/` (for example, `@file:///tmp/file.txt`).\n\n~~~bash\nbeeper-desktop-cli --arg @data://file.txt\n~~~\n\n## Linking different Go SDK versions\n\nYou can link the CLI against a different version of the Beeper Desktop Go SDK\nfor development purposes using the `./scripts/link` script.\n\nTo link to a specific version from a repository (version can be a branch,\ngit tag, or commit hash):\n\n~~~bash\n./scripts/link github.com/org/repo@version\n~~~\n\nTo link to a local copy of the SDK:\n\n~~~bash\n./scripts/link ../path/to/beeperdesktopapi-go\n~~~\n\nIf you run the link script without any arguments, it will default to `../beeperdesktopapi-go`.\n", + "# CLI for Beeper Desktop\n\nThe official CLI for the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/).\n\n\n\n## Installation\n\n### Installing with Go\n\nTo test or install the CLI locally, you need [Go](https://go.dev/doc/install) version 1.22 or later installed.\n\n~~~sh\ngo install 'github.com/beeper/desktop-api-cli/cmd/beeper-desktop@latest'\n~~~\n\nOnce you have run `go install`, the binary is placed in your Go bin directory:\n\n- **Default location**: `$HOME/go/bin` (or `$GOPATH/bin` if GOPATH is set)\n- **Check your path**: Run `go env GOPATH` to see the base directory\n\nIf commands aren't found after installation, add the Go bin directory to your PATH:\n\n~~~sh\n# Add to your shell profile (.zshrc, .bashrc, etc.)\nexport PATH=\"$PATH:$(go env GOPATH)/bin\"\n~~~\n\n\n\n### Running Locally\n\nAfter cloning the git repository for this project, you can use the\n`scripts/run` script to run the tool locally:\n\n~~~sh\n./scripts/run args...\n~~~\n\n## Usage\n\nThe CLI follows a resource-based command structure:\n\n~~~sh\nbeeper-desktop [resource] [flags...]\n~~~\n\n~~~sh\nbeeper-desktop chats search \\\n --access-token 'My Access Token' \\\n --account-id matrix \\\n --account-id discordgo \\\n --account-id local-whatsapp_ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --include-muted \\\n --limit 3 \\\n --type single\n~~~\n\nFor details about specific commands, use the `--help` flag.\n\n### Environment variables\n\n| Environment variable | Description | Required |\n| --------------------- | --------------------------------------------------------------------------------------------------------------- | -------- |\n| `BEEPER_ACCESS_TOKEN` | Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. | yes |\n\n### Global flags\n\n- `--access-token` - Bearer access token obtained via OAuth2 PKCE flow or created in-app. Required for authenticated API operations. (can also be set with `BEEPER_ACCESS_TOKEN` env var)\n- `--help` - Show command line usage\n- `--debug` - Enable debug logging (includes HTTP request/response details)\n- `--version`, `-v` - Show the CLI version\n- `--base-url` - Use a custom API backend URL\n- `--format` - Change the output format (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--format-error` - Change the output format for errors (`auto`, `explore`, `json`, `jsonl`, `pretty`, `raw`, `yaml`)\n- `--transform` - Transform the data output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n- `--transform-error` - Transform the error output using [GJSON syntax](https://github.com/tidwall/gjson/blob/master/SYNTAX.md)\n\n### Passing files as arguments\n\nTo pass files to your API, you can use the `@myfile.ext` syntax:\n\n~~~bash\nbeeper-desktop --arg @abe.jpg\n~~~\n\nFiles can also be passed inside JSON or YAML blobs:\n\n~~~bash\nbeeper-desktop --arg '{image: \"@abe.jpg\"}'\n# Equivalent:\nbeeper-desktop < --username '\\@abe'\n~~~\n\n#### Explicit encoding\n\nFor JSON endpoints, the CLI tool does filetype sniffing to determine whether the\nfile contents should be sent as a string literal (for plain text files) or as a\nbase64-encoded string literal (for binary files). If you need to explicitly send\nthe file as either plain text or base64-encoded data, you can use\n`@file://myfile.txt` (for string encoding) or `@data://myfile.dat` (for\nbase64-encoding). Note that absolute paths will begin with `@file://` or\n`@data://`, followed by a third `/` (for example, `@file:///tmp/file.txt`).\n\n~~~bash\nbeeper-desktop --arg @data://file.txt\n~~~\n\n## Linking different Go SDK versions\n\nYou can link the CLI against a different version of the Beeper Desktop Go SDK\nfor development purposes using the `./scripts/link` script.\n\nTo link to a specific version from a repository (version can be a branch,\ngit tag, or commit hash):\n\n~~~bash\n./scripts/link github.com/org/repo@version\n~~~\n\nTo link to a local copy of the SDK:\n\n~~~bash\n./scripts/link ../path/to/beeperdesktopapi-go\n~~~\n\nIf you run the link script without any arguments, it will default to `../beeperdesktopapi-go`.\n", }, { language: 'go', diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts index 5b10e8f0..2349c2fb 100644 --- a/packages/mcp-server/src/methods.ts +++ b/packages/mcp-server/src/methods.ts @@ -22,6 +22,12 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/v1/search', }, + { + clientCallName: 'client.accounts.retrieve', + fullyQualifiedName: 'accounts.retrieve', + httpMethod: 'get', + httpPath: '/v1/accounts/{accountID}', + }, { clientCallName: 'client.accounts.list', fullyQualifiedName: 'accounts.list', @@ -40,12 +46,72 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/v1/accounts/{accountID}/contacts', }, + { + clientCallName: 'client.bridges.retrieve', + fullyQualifiedName: 'bridges.retrieve', + httpMethod: 'get', + httpPath: '/v1/bridges/{bridgeID}', + }, { clientCallName: 'client.bridges.list', fullyQualifiedName: 'bridges.list', httpMethod: 'get', httpPath: '/v1/bridges', }, + { + clientCallName: 'client.bridges.retrieveCapabilities', + fullyQualifiedName: 'bridges.retrieveCapabilities', + httpMethod: 'get', + httpPath: '/v1/bridges/{bridgeID}/capabilities', + }, + { + clientCallName: 'client.bridges.loginFlows.list', + fullyQualifiedName: 'bridges.loginFlows.list', + httpMethod: 'get', + httpPath: '/v1/bridges/{bridgeID}/login-flows', + }, + { + clientCallName: 'client.bridges.connections.retrieve', + fullyQualifiedName: 'bridges.connections.retrieve', + httpMethod: 'get', + httpPath: '/v1/bridges/{bridgeID}/connections/{loginID}', + }, + { + clientCallName: 'client.bridges.connections.list', + fullyQualifiedName: 'bridges.connections.list', + httpMethod: 'get', + httpPath: '/v1/bridges/{bridgeID}/connections', + }, + { + clientCallName: 'client.bridges.connections.remove', + fullyQualifiedName: 'bridges.connections.remove', + httpMethod: 'post', + httpPath: '/v1/bridges/{bridgeID}/connections/{loginID}/remove', + }, + { + clientCallName: 'client.bridges.loginSessions.create', + fullyQualifiedName: 'bridges.loginSessions.create', + httpMethod: 'post', + httpPath: '/v1/bridges/{bridgeID}/login-sessions', + }, + { + clientCallName: 'client.bridges.loginSessions.retrieve', + fullyQualifiedName: 'bridges.loginSessions.retrieve', + httpMethod: 'get', + httpPath: '/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}', + }, + { + clientCallName: 'client.bridges.loginSessions.cancel', + fullyQualifiedName: 'bridges.loginSessions.cancel', + httpMethod: 'delete', + httpPath: '/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}', + }, + { + clientCallName: 'client.bridges.loginSessions.steps.submit', + fullyQualifiedName: 'bridges.loginSessions.steps.submit', + httpMethod: 'post', + httpPath: '/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}/steps/{stepID}', + }, { clientCallName: 'client.chats.create', fullyQualifiedName: 'chats.create', @@ -197,10 +263,10 @@ export const sdkMethods: SdkMethod[] = [ httpPath: '/v1/info', }, { - clientCallName: 'client.app.status', - fullyQualifiedName: 'app.status', + clientCallName: 'client.app.session', + fullyQualifiedName: 'app.session', httpMethod: 'get', - httpPath: '/v1/app/status', + httpPath: '/v1/app/session', }, { clientCallName: 'client.app.login.email', @@ -227,227 +293,76 @@ export const sdkMethods: SdkMethod[] = [ httpPath: '/v1/app/login/start', }, { - clientCallName: 'client.app.e2ee.recoveryCode.markBackedUp', - fullyQualifiedName: 'app.e2ee.recoveryCode.markBackedUp', - httpMethod: 'post', - httpPath: '/v1/app/e2ee/recovery-code/mark-backed-up', - }, - { - clientCallName: 'client.app.e2ee.recoveryCode.verify', - fullyQualifiedName: 'app.e2ee.recoveryCode.verify', - httpMethod: 'post', - httpPath: '/v1/app/e2ee/recovery-code/verify', - }, - { - clientCallName: 'client.app.e2ee.recoveryCode.reset.create', - fullyQualifiedName: 'app.e2ee.recoveryCode.reset.create', - httpMethod: 'post', - httpPath: '/v1/app/e2ee/recovery-code/reset', - }, - { - clientCallName: 'client.app.e2ee.recoveryCode.reset.confirm', - fullyQualifiedName: 'app.e2ee.recoveryCode.reset.confirm', + clientCallName: 'client.app.login.verification.recoveryKey.verify', + fullyQualifiedName: 'app.login.verification.recoveryKey.verify', httpMethod: 'post', - httpPath: '/v1/app/e2ee/recovery-code/reset/confirm', + httpPath: '/v1/app/login/verification/recovery-key', }, { - clientCallName: 'client.app.e2ee.verification.create', - fullyQualifiedName: 'app.e2ee.verification.create', + clientCallName: 'client.app.login.verification.recoveryKey.reset.create', + fullyQualifiedName: 'app.login.verification.recoveryKey.reset.create', httpMethod: 'post', - httpPath: '/v1/app/e2ee/verification', + httpPath: '/v1/app/login/verification/recovery-key/reset', }, { - clientCallName: 'client.app.e2ee.verification.accept', - fullyQualifiedName: 'app.e2ee.verification.accept', + clientCallName: 'client.app.login.verification.recoveryKey.reset.confirm', + fullyQualifiedName: 'app.login.verification.recoveryKey.reset.confirm', httpMethod: 'post', - httpPath: '/v1/app/e2ee/verification/{verificationID}/accept', + httpPath: '/v1/app/login/verification/recovery-key/reset/confirm', }, { - clientCallName: 'client.app.e2ee.verification.cancel', - fullyQualifiedName: 'app.e2ee.verification.cancel', + clientCallName: 'client.app.verifications.create', + fullyQualifiedName: 'app.verifications.create', httpMethod: 'post', - httpPath: '/v1/app/e2ee/verification/{verificationID}/cancel', + httpPath: '/v1/app/verifications', }, { - clientCallName: 'client.app.e2ee.verification.qr.confirmScanned', - fullyQualifiedName: 'app.e2ee.verification.qr.confirmScanned', - httpMethod: 'post', - httpPath: '/v1/app/e2ee/verification/{verificationID}/qr/confirm-scanned', - }, - { - clientCallName: 'client.app.e2ee.verification.qr.scan', - fullyQualifiedName: 'app.e2ee.verification.qr.scan', - httpMethod: 'post', - httpPath: '/v1/app/e2ee/verification/qr/scan', - }, - { - clientCallName: 'client.app.e2ee.verification.sas.confirm', - fullyQualifiedName: 'app.e2ee.verification.sas.confirm', - httpMethod: 'post', - httpPath: '/v1/app/e2ee/verification/{verificationID}/sas/confirm', - }, - { - clientCallName: 'client.app.e2ee.verification.sas.start', - fullyQualifiedName: 'app.e2ee.verification.sas.start', - httpMethod: 'post', - httpPath: '/v1/app/e2ee/verification/{verificationID}/sas/start', - }, - { - clientCallName: 'client.matrix.users.retrieveProfile', - fullyQualifiedName: 'matrix.users.retrieveProfile', - httpMethod: 'get', - httpPath: '/_matrix/client/v3/profile/{userId}', - }, - { - clientCallName: 'client.matrix.users.accountData.retrieve', - fullyQualifiedName: 'matrix.users.accountData.retrieve', - httpMethod: 'get', - httpPath: '/_matrix/client/v3/user/{userId}/account_data/{type}', - }, - { - clientCallName: 'client.matrix.users.accountData.update', - fullyQualifiedName: 'matrix.users.accountData.update', - httpMethod: 'put', - httpPath: '/_matrix/client/v3/user/{userId}/account_data/{type}', - }, - { - clientCallName: 'client.matrix.rooms.create', - fullyQualifiedName: 'matrix.rooms.create', - httpMethod: 'post', - httpPath: '/_matrix/client/v3/createRoom', - }, - { - clientCallName: 'client.matrix.rooms.join', - fullyQualifiedName: 'matrix.rooms.join', - httpMethod: 'post', - httpPath: '/_matrix/client/v3/join/{roomIdOrAlias}', - }, - { - clientCallName: 'client.matrix.rooms.leave', - fullyQualifiedName: 'matrix.rooms.leave', - httpMethod: 'post', - httpPath: '/_matrix/client/v3/rooms/{roomId}/leave', - }, - { - clientCallName: 'client.matrix.rooms.accountData.retrieve', - fullyQualifiedName: 'matrix.rooms.accountData.retrieve', - httpMethod: 'get', - httpPath: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', - }, - { - clientCallName: 'client.matrix.rooms.accountData.update', - fullyQualifiedName: 'matrix.rooms.accountData.update', - httpMethod: 'put', - httpPath: '/_matrix/client/v3/user/{userId}/rooms/{roomId}/account_data/{type}', - }, - { - clientCallName: 'client.matrix.rooms.state.retrieve', - fullyQualifiedName: 'matrix.rooms.state.retrieve', - httpMethod: 'get', - httpPath: '/_matrix/client/v3/rooms/{roomId}/state/{eventType}/{stateKey}', - }, - { - clientCallName: 'client.matrix.rooms.state.list', - fullyQualifiedName: 'matrix.rooms.state.list', + clientCallName: 'client.app.verifications.retrieve', + fullyQualifiedName: 'app.verifications.retrieve', httpMethod: 'get', - httpPath: '/_matrix/client/v3/rooms/{roomId}/state', + httpPath: '/v1/app/verifications/{verificationID}', }, { - clientCallName: 'client.matrix.rooms.events.retrieve', - fullyQualifiedName: 'matrix.rooms.events.retrieve', + clientCallName: 'client.app.verifications.list', + fullyQualifiedName: 'app.verifications.list', httpMethod: 'get', - httpPath: '/_matrix/client/v3/rooms/{roomId}/event/{eventId}', - }, - { - clientCallName: 'client.matrix.bridges.auth.listFlows', - fullyQualifiedName: 'matrix.bridges.auth.listFlows', - httpMethod: 'get', - httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/flows', - }, - { - clientCallName: 'client.matrix.bridges.auth.listLogins', - fullyQualifiedName: 'matrix.bridges.auth.listLogins', - httpMethod: 'get', - httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logins', - }, - { - clientCallName: 'client.matrix.bridges.auth.logout', - fullyQualifiedName: 'matrix.bridges.auth.logout', - httpMethod: 'post', - httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/logout/{loginID}', - }, - { - clientCallName: 'client.matrix.bridges.auth.startLogin', - fullyQualifiedName: 'matrix.bridges.auth.startLogin', - httpMethod: 'post', - httpPath: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/start/{flowID}', + httpPath: '/v1/app/verifications', }, { - clientCallName: 'client.matrix.bridges.auth.submitCookies', - fullyQualifiedName: 'matrix.bridges.auth.submitCookies', + clientCallName: 'client.app.verifications.accept', + fullyQualifiedName: 'app.verifications.accept', httpMethod: 'post', - httpPath: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/cookies', + httpPath: '/v1/app/verifications/{verificationID}/accept', }, { - clientCallName: 'client.matrix.bridges.auth.submitUserInput', - fullyQualifiedName: 'matrix.bridges.auth.submitUserInput', + clientCallName: 'client.app.verifications.cancel', + fullyQualifiedName: 'app.verifications.cancel', httpMethod: 'post', - httpPath: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/user_input', + httpPath: '/v1/app/verifications/{verificationID}/cancel', }, { - clientCallName: 'client.matrix.bridges.auth.waitForStep', - fullyQualifiedName: 'matrix.bridges.auth.waitForStep', + clientCallName: 'client.app.verifications.qr.confirmScanned', + fullyQualifiedName: 'app.verifications.qr.confirmScanned', httpMethod: 'post', - httpPath: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/login/step/{loginProcessID}/{stepID}/display_and_wait', - }, - { - clientCallName: 'client.matrix.bridges.auth.whoami', - fullyQualifiedName: 'matrix.bridges.auth.whoami', - httpMethod: 'get', - httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/whoami', - }, - { - clientCallName: 'client.matrix.bridges.contacts.list', - fullyQualifiedName: 'matrix.bridges.contacts.list', - httpMethod: 'get', - httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/contacts', + httpPath: '/v1/app/verifications/{verificationID}/qr/confirm-scanned', }, { - clientCallName: 'client.matrix.bridges.users.resolve', - fullyQualifiedName: 'matrix.bridges.users.resolve', - httpMethod: 'get', - httpPath: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/resolve_identifier/{identifier}', - }, - { - clientCallName: 'client.matrix.bridges.users.search', - fullyQualifiedName: 'matrix.bridges.users.search', + clientCallName: 'client.app.verifications.qr.scan', + fullyQualifiedName: 'app.verifications.qr.scan', httpMethod: 'post', - httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/search_users', + httpPath: '/v1/app/verifications/qr/scan', }, { - clientCallName: 'client.matrix.bridges.rooms.createDm', - fullyQualifiedName: 'matrix.bridges.rooms.createDm', + clientCallName: 'client.app.verifications.sas.confirm', + fullyQualifiedName: 'app.verifications.sas.confirm', httpMethod: 'post', - httpPath: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_dm/{identifier}', + httpPath: '/v1/app/verifications/{verificationID}/sas/confirm', }, { - clientCallName: 'client.matrix.bridges.rooms.createGroup', - fullyQualifiedName: 'matrix.bridges.rooms.createGroup', + clientCallName: 'client.app.verifications.sas.start', + fullyQualifiedName: 'app.verifications.sas.start', httpMethod: 'post', - httpPath: - '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/create_group/{groupType}', - }, - { - clientCallName: 'client.matrix.bridges.capabilities.retrieve', - fullyQualifiedName: 'matrix.bridges.capabilities.retrieve', - httpMethod: 'get', - httpPath: '/_matrix/client/unstable/com.beeper.bridge/{bridgeID}/_matrix/provision/v3/capabilities', + httpPath: '/v1/app/verifications/{verificationID}/sas/start', }, ]; diff --git a/src/client.ts b/src/client.ts index 232b4ac7..1d44dd43 100644 --- a/src/client.ts +++ b/src/client.ts @@ -37,7 +37,6 @@ import { AssetUploadResponse, Assets, } from './resources/assets'; -import { BridgeAvailability, BridgeListResponse, Bridges } from './resources/bridges'; import { Info, InfoRetrieveResponse } from './resources/info'; import { MessageDeleteParams, @@ -50,17 +49,40 @@ import { MessageUpdateResponse, Messages, } from './resources/messages'; -import { Account, AccountListResponse, Accounts } from './resources/accounts/accounts'; +import { + Account, + AccountBridge, + AccountListResponse, + AccountRetrieveResponse, + Accounts, +} from './resources/accounts/accounts'; import { App, - AppStatusResponse, + AppSessionResponse, LoginRegistrationRequiredResponse, LoginResponse, LoginResponseOutput, - RecoveryCodeResetResponse, - StartVerificationResponse, - StateMutationResponse, + RecoveryKeyResetResponse, + SessionMutationResponse, + Verification, + VerificationResponse, } from './resources/app/app'; +import { + Bridge, + BridgeConnection, + BridgeListResponse, + BridgeRetrieveResponse, + Bridges, + CookieField, + DisappearingTimerCapability, + GroupFieldCapability, + GroupTypeCapabilities, + LoginFlow, + LoginInputField, + LoginSession, + ProvisioningCapabilities, + ResolveIdentifierCapabilities, +} from './resources/bridges/bridges'; import { Chat, ChatArchiveParams, @@ -80,7 +102,6 @@ import { Chats, ChatsCursorSearch, } from './resources/chats/chats'; -import { Matrix } from './resources/matrix/matrix'; import { type Fetch } from './internal/builtin-types'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; @@ -862,7 +883,7 @@ export class BeeperDesktop extends BaseBeeperDesktop { */ accounts: API.Accounts = new API.Accounts(this); /** - * Manage bridge-backed account types and account availability + * Manage bridge-backed account types, connections, and login sessions */ bridges: API.Bridges = new API.Bridges(this); /** @@ -885,10 +906,6 @@ export class BeeperDesktop extends BaseBeeperDesktop { * Manage Beeper app login and encrypted messaging setup */ app: API.App = new API.App(this); - /** - * Matrix-compatible APIs for accounts, rooms, and connected network bridges. - */ - matrix: API.Matrix = new API.Matrix(this); } BeeperDesktop.Accounts = Accounts; @@ -898,7 +915,6 @@ BeeperDesktop.Messages = Messages; BeeperDesktop.Assets = Assets; BeeperDesktop.Info = Info; BeeperDesktop.App = App; -BeeperDesktop.Matrix = Matrix; export declare namespace BeeperDesktop { export type RequestOptions = Opts.RequestOptions; @@ -919,11 +935,28 @@ export declare namespace BeeperDesktop { type SearchParams as SearchParams, }; - export { Accounts as Accounts, type Account as Account, type AccountListResponse as AccountListResponse }; + export { + Accounts as Accounts, + type Account as Account, + type AccountBridge as AccountBridge, + type AccountRetrieveResponse as AccountRetrieveResponse, + type AccountListResponse as AccountListResponse, + }; export { Bridges as Bridges, - type BridgeAvailability as BridgeAvailability, + type Bridge as Bridge, + type BridgeConnection as BridgeConnection, + type CookieField as CookieField, + type DisappearingTimerCapability as DisappearingTimerCapability, + type GroupFieldCapability as GroupFieldCapability, + type GroupTypeCapabilities as GroupTypeCapabilities, + type LoginFlow as LoginFlow, + type LoginInputField as LoginInputField, + type LoginSession as LoginSession, + type ProvisioningCapabilities as ProvisioningCapabilities, + type ResolveIdentifierCapabilities as ResolveIdentifierCapabilities, + type BridgeRetrieveResponse as BridgeRetrieveResponse, type BridgeListResponse as BridgeListResponse, }; @@ -977,14 +1010,14 @@ export declare namespace BeeperDesktop { type LoginRegistrationRequiredResponse as LoginRegistrationRequiredResponse, type LoginResponse as LoginResponse, type LoginResponseOutput as LoginResponseOutput, - type RecoveryCodeResetResponse as RecoveryCodeResetResponse, - type StartVerificationResponse as StartVerificationResponse, - type StateMutationResponse as StateMutationResponse, - type AppStatusResponse as AppStatusResponse, + type RecoveryKeyResetResponse as RecoveryKeyResetResponse, + type SessionMutationResponse as SessionMutationResponse, + type Verification as Verification, + type VerificationResponse as VerificationResponse, + type AppSessionResponse as AppSessionResponse, }; - export { Matrix as Matrix }; - + export type APIError = API.APIError; export type AppStateSnapshot = API.AppStateSnapshot; export type Attachment = API.Attachment; export type Error = API.Error; diff --git a/src/resources/accounts/accounts.ts b/src/resources/accounts/accounts.ts index c3c997f0..4ac2f8ee 100644 --- a/src/resources/accounts/accounts.ts +++ b/src/resources/accounts/accounts.ts @@ -12,6 +12,7 @@ import { } from './contacts'; import { APIPromise } from '../../core/api-promise'; import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; /** * Manage connected chat accounts @@ -19,6 +20,18 @@ import { RequestOptions } from '../../internal/request-options'; export class BaseAccounts extends APIResource { static override readonly _key: readonly ['accounts'] = Object.freeze(['accounts'] as const); + /** + * Get one Chat Account connected to this Beeper Desktop instance. + * + * @example + * ```ts + * const account = await client.accounts.retrieve('accountID'); + * ``` + */ + retrieve(accountID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/accounts/${accountID}`, options); + } + /** * List Chat Accounts connected to this Beeper Desktop instance, including bridge * metadata and network identity. @@ -54,43 +67,128 @@ export interface Account { /** * Bridge metadata for the account. Available in Beeper Desktop v4.2.785+. */ - bridge: Account.Bridge; + bridge: AccountBridge; + + /** + * Current connection status for this account. + */ + status: + | 'connected' + | 'connecting' + | 'backfilling' + | 'connection_required' + | 'reconnect_required' + | 'attention_required' + | 'disconnected' + | 'disabled'; /** * User the account belongs to. */ user: Shared.User; + /** + * Runtime chat/message capabilities for this connected account, when available. + */ + capabilities?: { [key: string]: unknown }; + + /** + * Bridge login identity for this account, when known. This is not guaranteed to be + * one-to-one with accountID. + */ + loginID?: string; + /** * Human-friendly network name for the account. Omitted when the network is * unknown. */ network?: string; + + /** + * Human-friendly account status text. + */ + statusText?: string; } -export namespace Account { +/** + * Bridge metadata for the account. Available in Beeper Desktop v4.2.785+. + */ +export interface AccountBridge { + /** + * Bridge instance identifier. Matrix and cloud bridges often use the bridge type + * (for example matrix or discordgo); local bridges use a local bridge ID (for + * example local-whatsapp). Available in Beeper Desktop v4.2.785+. + */ + id: string; + + /** + * Bridge provider for the account. Available in Beeper Desktop v4.2.785+. + */ + provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; + + /** + * Bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, or twitter. + * Available in Beeper Desktop v4.2.785+. + */ + type: string; +} + +/** + * A chat account added to Beeper. + */ +export interface AccountRetrieveResponse { + /** + * Chat account added to Beeper. Use this to route account-scoped actions. Examples + * include matrix for Beeper/Matrix, discordgo for a cloud bridge, + * slackgo.TEAM-USER for workspace-scoped cloud bridges, and local-whatsapp*ba*... + * for local bridges. + */ + accountID: string; + /** * Bridge metadata for the account. Available in Beeper Desktop v4.2.785+. */ - export interface Bridge { - /** - * Bridge instance identifier. Matrix and cloud bridges often use the bridge type - * (for example matrix or discordgo); local bridges use a local bridge ID (for - * example local-whatsapp). Available in Beeper Desktop v4.2.785+. - */ - id: string; - - /** - * Bridge provider for the account. Available in Beeper Desktop v4.2.785+. - */ - provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; - - /** - * Bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, or twitter. - * Available in Beeper Desktop v4.2.785+. - */ - type: string; - } + bridge: AccountBridge; + + /** + * Current connection status for this account. + */ + status: + | 'connected' + | 'connecting' + | 'backfilling' + | 'connection_required' + | 'reconnect_required' + | 'attention_required' + | 'disconnected' + | 'disabled'; + + /** + * User the account belongs to. + */ + user: Shared.User; + + /** + * Runtime chat/message capabilities for this connected account, when available. + */ + capabilities?: { [key: string]: unknown }; + + /** + * Bridge login identity for this account, when known. This is not guaranteed to be + * one-to-one with accountID. + */ + loginID?: string; + + /** + * Human-friendly network name for the account. Omitted when the network is + * unknown. + */ + network?: string; + + /** + * Human-friendly account status text. + */ + statusText?: string; } /** @@ -103,7 +201,12 @@ Accounts.Contacts = Contacts; Accounts.BaseContacts = BaseContacts; export declare namespace Accounts { - export { type Account as Account, type AccountListResponse as AccountListResponse }; + export { + type Account as Account, + type AccountBridge as AccountBridge, + type AccountRetrieveResponse as AccountRetrieveResponse, + type AccountListResponse as AccountListResponse, + }; export { Contacts as Contacts, diff --git a/src/resources/accounts/index.ts b/src/resources/accounts/index.ts index 1249a9b1..c63c2c5d 100644 --- a/src/resources/accounts/index.ts +++ b/src/resources/accounts/index.ts @@ -1,6 +1,13 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Accounts, BaseAccounts, type Account, type AccountListResponse } from './accounts'; +export { + Accounts, + BaseAccounts, + type Account, + type AccountBridge, + type AccountRetrieveResponse, + type AccountListResponse, +} from './accounts'; export { Contacts, BaseContacts, diff --git a/src/resources/app/app.ts b/src/resources/app/app.ts index c102038f..65c05a3d 100644 --- a/src/resources/app/app.ts +++ b/src/resources/app/app.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; -import * as LoginAPI from './login'; +import * as LoginAPI from './login/login'; import { BaseLogin, Login, @@ -12,9 +12,19 @@ import { LoginResponseParams, LoginResponseResponse, LoginStartResponse, -} from './login'; -import * as E2eeAPI from './e2ee/e2ee'; -import { BaseE2ee, E2ee as E2eeAPIE2ee } from './e2ee/e2ee'; +} from './login/login'; +import * as VerificationsAPI from './verifications/verifications'; +import { + BaseVerifications, + VerificationAcceptResponse, + VerificationCancelParams, + VerificationCancelResponse, + VerificationCreateParams, + VerificationCreateResponse, + VerificationListResponse, + VerificationRetrieveResponse, + Verifications, +} from './verifications/verifications'; import { APIPromise } from '../../core/api-promise'; import { RequestOptions } from '../../internal/request-options'; @@ -29,8 +39,8 @@ export class BaseApp extends APIResource { * This endpoint is public before sign-in so apps can discover that login is * needed; after sign-in, pass a read token. */ - status(options?: RequestOptions): APIPromise { - return this._client.get('/v1/app/status', options); + session(options?: RequestOptions): APIPromise { + return this._client.get('/v1/app/session', options); } } /** @@ -38,7 +48,7 @@ export class BaseApp extends APIResource { */ export class App extends BaseApp { login: LoginAPI.Login = new LoginAPI.Login(this._client); - e2ee: E2eeAPI.E2ee = new E2eeAPI.E2ee(this._client); + verifications: VerificationsAPI.Verifications = new VerificationsAPI.Verifications(this._client); } export interface LoginRegistrationRequiredResponse { @@ -96,11 +106,6 @@ export namespace LoginRegistrationRequiredResponse { } export interface LoginResponse { - /** - * Current onboarding state after sign-in. - */ - appState: LoginResponse.AppState; - /** * Desktop API credentials for the signed-in app session. */ @@ -110,17 +115,67 @@ export interface LoginResponse { * Account credentials for first-party app setup. */ matrix: LoginResponse.Matrix; + + /** + * Current app session state after sign-in. + */ + session: LoginResponse.Session; } export namespace LoginResponse { /** - * Current onboarding state after sign-in. + * Desktop API credentials for the signed-in app session. + */ + export interface DesktopAPI { + /** + * Desktop API access token for this app session. + */ + accessToken: string; + + /** + * Granted Desktop API scopes. + */ + scope: 'read write'; + + /** + * Access token type. + */ + tokenType: 'Bearer'; + } + + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Current app session state after sign-in. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -137,19 +192,19 @@ export namespace LoginResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -163,7 +218,7 @@ export namespace LoginResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -178,7 +233,7 @@ export namespace LoginResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -193,10 +248,10 @@ export namespace LoginResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -214,7 +269,7 @@ export namespace LoginResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -253,61 +308,59 @@ export namespace LoginResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -327,97 +380,122 @@ export namespace LoginResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. */ - decimals: string; + data: string; + } + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } +} - /** - * Desktop API credentials for the signed-in app session. - */ - export interface DesktopAPI { +export type LoginResponseOutput = LoginResponseOutput.UnionMember0 | LoginResponseOutput.UnionMember1; + +export namespace LoginResponseOutput { + export interface UnionMember0 { /** - * Desktop API access token for this app session. + * Desktop API credentials for the signed-in app session. */ - accessToken: string; + desktopAPI: UnionMember0.DesktopAPI; /** - * Granted Desktop API scopes. + * Account credentials for first-party app setup. */ - scope: 'read write'; + matrix: UnionMember0.Matrix; /** - * Access token type. + * Current app session state after sign-in. */ - tokenType: 'Bearer'; + session: UnionMember0.Session; } - /** - * Account credentials for first-party app setup. - */ - export interface Matrix { + export namespace UnionMember0 { /** - * Account access token. Returned once for first-party app setup. + * Desktop API credentials for the signed-in app session. */ - accessToken: string; + export interface DesktopAPI { + /** + * Desktop API access token for this app session. + */ + accessToken: string; - /** - * Current device ID. - */ - deviceID: string; + /** + * Granted Desktop API scopes. + */ + scope: 'read write'; - /** - * Beeper server URL for this account. - */ - homeserver: string; + /** + * Access token type. + */ + tokenType: 'Bearer'; + } /** - * Signed-in Beeper user ID. + * Account credentials for first-party app setup. */ - userID: string; - } -} - -export type LoginResponseOutput = LoginResponseOutput.UnionMember0 | LoginResponseOutput.UnionMember1; + export interface Matrix { + /** + * Account access token. Returned once for first-party app setup. + */ + accessToken: string; -export namespace LoginResponseOutput { - export interface UnionMember0 { - /** - * Current onboarding state after sign-in. - */ - appState: UnionMember0.AppState; + /** + * Current device ID. + */ + deviceID: string; - /** - * Desktop API credentials for the signed-in app session. - */ - desktopAPI: UnionMember0.DesktopAPI; + /** + * Beeper server URL for this account. + */ + homeserver: string; - /** - * Account credentials for first-party app setup. - */ - matrix: UnionMember0.Matrix; - } + /** + * Signed-in Beeper user ID. + */ + userID: string; + } - export namespace UnionMember0 { /** - * Current onboarding state after sign-in. + * Current app session state after sign-in. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -434,19 +512,19 @@ export namespace LoginResponseOutput { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -460,7 +538,7 @@ export namespace LoginResponseOutput { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -475,7 +553,7 @@ export namespace LoginResponseOutput { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -490,10 +568,10 @@ export namespace LoginResponseOutput { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -511,7 +589,7 @@ export namespace LoginResponseOutput { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -550,61 +628,59 @@ export namespace LoginResponseOutput { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -624,65 +700,45 @@ export namespace LoginResponseOutput { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. */ - decimals: string; + id: string; /** - * Emoji sequence to compare on both devices. + * Other device display name, if known. */ - emojis: string; + name?: string; } - } - } - - /** - * Desktop API credentials for the signed-in app session. - */ - export interface DesktopAPI { - /** - * Desktop API access token for this app session. - */ - accessToken: string; - - /** - * Granted Desktop API scopes. - */ - scope: 'read write'; - - /** - * Access token type. - */ - tokenType: 'Bearer'; - } - - /** - * Account credentials for first-party app setup. - */ - export interface Matrix { - /** - * Account access token. Returned once for first-party app setup. - */ - accessToken: string; - /** - * Current device ID. - */ - deviceID: string; + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } - /** - * Beeper server URL for this account. - */ - homeserver: string; + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; - /** - * Signed-in Beeper user ID. - */ - userID: string; + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } } } @@ -741,27 +797,27 @@ export namespace LoginResponseOutput { } } -export interface RecoveryCodeResetResponse { +export interface RecoveryKeyResetResponse { /** - * Current onboarding state after creating the new recovery key. + * New recovery key. Show it once and ask the user to save it. */ - appState: RecoveryCodeResetResponse.AppState; + recoveryKey: string; /** - * New recovery key. Show it once and ask the user to save it. + * Current session state after creating the new recovery key. */ - recoveryCode: string; + session: RecoveryKeyResetResponse.Session; } -export namespace RecoveryCodeResetResponse { +export namespace RecoveryKeyResetResponse { /** - * Current onboarding state after creating the new recovery key. + * Current session state after creating the new recovery key. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -778,19 +834,19 @@ export namespace RecoveryCodeResetResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -804,7 +860,7 @@ export namespace RecoveryCodeResetResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -819,7 +875,7 @@ export namespace RecoveryCodeResetResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -834,10 +890,10 @@ export namespace RecoveryCodeResetResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -855,7 +911,7 @@ export namespace RecoveryCodeResetResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -894,61 +950,59 @@ export namespace RecoveryCodeResetResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -968,44 +1022,64 @@ export namespace RecoveryCodeResetResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. */ - decimals: string; + id: string; + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } } -export interface StartVerificationResponse { - /** - * Current onboarding state after starting verification. - */ - appState: StartVerificationResponse.AppState; - +export interface SessionMutationResponse { /** - * Verification ID to pass in verification action paths. + * Current app session state. */ - verificationID: string; + session: SessionMutationResponse.Session; } -export namespace StartVerificationResponse { +export namespace SessionMutationResponse { /** - * Current onboarding state after starting verification. + * Current app session state. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -1022,19 +1096,19 @@ export namespace StartVerificationResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -1048,7 +1122,7 @@ export namespace StartVerificationResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -1063,7 +1137,7 @@ export namespace StartVerificationResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -1078,10 +1152,10 @@ export namespace StartVerificationResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -1099,7 +1173,7 @@ export namespace StartVerificationResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -1138,61 +1212,59 @@ export namespace StartVerificationResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -1212,39 +1284,186 @@ export namespace StartVerificationResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. */ - decimals: string; + id: string; + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } } -export interface StateMutationResponse { +/** + * Trusted-device verification progress. + */ +export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; +} + +export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } +} + +export interface VerificationResponse { /** - * Current onboarding state after the requested step. + * Current session state. */ - appState: StateMutationResponse.AppState; + session: VerificationResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: VerificationResponse.Verification; } -export namespace StateMutationResponse { +export namespace VerificationResponse { /** - * Current onboarding state after the requested step. + * Current session state. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -1261,19 +1480,19 @@ export namespace StateMutationResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -1287,7 +1506,7 @@ export namespace StateMutationResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -1302,7 +1521,7 @@ export namespace StateMutationResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -1317,10 +1536,10 @@ export namespace StateMutationResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -1338,7 +1557,7 @@ export namespace StateMutationResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -1377,61 +1596,59 @@ export namespace StateMutationResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -1451,28 +1668,170 @@ export namespace StateMutationResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. */ - decimals: string; + data: string; + } + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } } -export interface AppStatusResponse { +export interface AppSessionResponse { /** * Encrypted messaging setup status. */ - e2ee: AppStatusResponse.E2ee; + e2ee: AppSessionResponse.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -1489,19 +1848,19 @@ export interface AppStatusResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppStatusResponse.Matrix; + matrix?: AppSessionResponse.Matrix; /** * Trusted-device verification progress. */ - verification?: AppStatusResponse.Verification; + verification?: AppSessionResponse.Verification; } -export namespace AppStatusResponse { +export namespace AppSessionResponse { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -1515,7 +1874,7 @@ export namespace AppStatusResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -1530,7 +1889,7 @@ export namespace AppStatusResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -1545,10 +1904,10 @@ export namespace AppStatusResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -1566,7 +1925,7 @@ export namespace AppStatusResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -1605,61 +1964,59 @@ export namespace AppStatusResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -1679,36 +2036,62 @@ export namespace AppStatusResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. */ - decimals: string; + id: string; + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } App.Login = Login; App.BaseLogin = BaseLogin; -App.E2ee = E2eeAPIE2ee; -App.BaseE2ee = BaseE2ee; +App.Verifications = Verifications; +App.BaseVerifications = BaseVerifications; export declare namespace App { export { type LoginRegistrationRequiredResponse as LoginRegistrationRequiredResponse, type LoginResponse as LoginResponse, type LoginResponseOutput as LoginResponseOutput, - type RecoveryCodeResetResponse as RecoveryCodeResetResponse, - type StartVerificationResponse as StartVerificationResponse, - type StateMutationResponse as StateMutationResponse, - type AppStatusResponse as AppStatusResponse, + type RecoveryKeyResetResponse as RecoveryKeyResetResponse, + type SessionMutationResponse as SessionMutationResponse, + type Verification as Verification, + type VerificationResponse as VerificationResponse, + type AppSessionResponse as AppSessionResponse, }; export { @@ -1723,5 +2106,15 @@ export declare namespace App { type LoginResponseParams as LoginResponseParams, }; - export { E2eeAPIE2ee as E2ee, BaseE2ee as BaseE2ee }; + export { + Verifications as Verifications, + BaseVerifications as BaseVerifications, + type VerificationCreateResponse as VerificationCreateResponse, + type VerificationRetrieveResponse as VerificationRetrieveResponse, + type VerificationListResponse as VerificationListResponse, + type VerificationAcceptResponse as VerificationAcceptResponse, + type VerificationCancelResponse as VerificationCancelResponse, + type VerificationCreateParams as VerificationCreateParams, + type VerificationCancelParams as VerificationCancelParams, + }; } diff --git a/src/resources/app/e2ee/e2ee.ts b/src/resources/app/e2ee/e2ee.ts deleted file mode 100644 index 20e3bd3f..00000000 --- a/src/resources/app/e2ee/e2ee.ts +++ /dev/null @@ -1,60 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as RecoveryCodeAPI from './recovery-code/recovery-code'; -import { - BaseRecoveryCode, - RecoveryCode, - RecoveryCodeMarkBackedUpResponse, - RecoveryCodeVerifyParams, - RecoveryCodeVerifyResponse, -} from './recovery-code/recovery-code'; -import * as VerificationAPI from './verification/verification'; -import { - BaseVerification, - Verification, - VerificationAcceptResponse, - VerificationCancelParams, - VerificationCancelResponse, - VerificationCreateParams, - VerificationCreateResponse, -} from './verification/verification'; - -/** - * Manage encrypted messaging setup - */ -export class BaseE2ee extends APIResource { - static override readonly _key: readonly ['app', 'e2ee'] = Object.freeze(['app', 'e2ee'] as const); -} -/** - * Manage encrypted messaging setup - */ -export class E2ee extends BaseE2ee { - recoveryCode: RecoveryCodeAPI.RecoveryCode = new RecoveryCodeAPI.RecoveryCode(this._client); - verification: VerificationAPI.Verification = new VerificationAPI.Verification(this._client); -} - -E2ee.RecoveryCode = RecoveryCode; -E2ee.BaseRecoveryCode = BaseRecoveryCode; -E2ee.Verification = Verification; -E2ee.BaseVerification = BaseVerification; - -export declare namespace E2ee { - export { - RecoveryCode as RecoveryCode, - BaseRecoveryCode as BaseRecoveryCode, - type RecoveryCodeMarkBackedUpResponse as RecoveryCodeMarkBackedUpResponse, - type RecoveryCodeVerifyResponse as RecoveryCodeVerifyResponse, - type RecoveryCodeVerifyParams as RecoveryCodeVerifyParams, - }; - - export { - Verification as Verification, - BaseVerification as BaseVerification, - type VerificationCreateResponse as VerificationCreateResponse, - type VerificationAcceptResponse as VerificationAcceptResponse, - type VerificationCancelResponse as VerificationCancelResponse, - type VerificationCreateParams as VerificationCreateParams, - type VerificationCancelParams as VerificationCancelParams, - }; -} diff --git a/src/resources/app/e2ee/index.ts b/src/resources/app/e2ee/index.ts deleted file mode 100644 index 13196e0a..00000000 --- a/src/resources/app/e2ee/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { E2ee, BaseE2ee } from './e2ee'; -export { - RecoveryCode, - BaseRecoveryCode, - type RecoveryCodeMarkBackedUpResponse, - type RecoveryCodeVerifyResponse, - type RecoveryCodeVerifyParams, -} from './recovery-code/index'; -export { - Verification, - BaseVerification, - type VerificationCreateResponse, - type VerificationAcceptResponse, - type VerificationCancelResponse, - type VerificationCreateParams, - type VerificationCancelParams, -} from './verification/index'; diff --git a/src/resources/app/e2ee/recovery-code.ts b/src/resources/app/e2ee/recovery-code.ts deleted file mode 100644 index 36813bdb..00000000 --- a/src/resources/app/e2ee/recovery-code.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './recovery-code/index'; diff --git a/src/resources/app/e2ee/recovery-code/recovery-code.ts b/src/resources/app/e2ee/recovery-code/recovery-code.ts deleted file mode 100644 index bfe4dd6d..00000000 --- a/src/resources/app/e2ee/recovery-code/recovery-code.ts +++ /dev/null @@ -1,550 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../../core/resource'; -import * as ResetAPI from './reset'; -import { - BaseReset, - Reset, - ResetConfirmParams, - ResetConfirmResponse, - ResetCreateParams, - ResetCreateResponse, -} from './reset'; -import { APIPromise } from '../../../../core/api-promise'; -import { RequestOptions } from '../../../../internal/request-options'; - -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ -export class BaseRecoveryCode extends APIResource { - static override readonly _key: readonly ['app', 'e2ee', 'recoveryCode'] = Object.freeze([ - 'app', - 'e2ee', - 'recoveryCode', - ] as const); - - /** - * Record that the user saved their recovery key. - */ - markBackedUp(options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/e2ee/recovery-code/mark-backed-up', options); - } - - /** - * Unlock encrypted messages with the user recovery key. - */ - verify(body: RecoveryCodeVerifyParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/e2ee/recovery-code/verify', { body, ...options }); - } -} -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ -export class RecoveryCode extends BaseRecoveryCode { - reset: ResetAPI.Reset = new ResetAPI.Reset(this._client); -} - -export interface RecoveryCodeMarkBackedUpResponse { - /** - * Current onboarding state after the requested step. - */ - appState: RecoveryCodeMarkBackedUpResponse.AppState; -} - -export namespace RecoveryCodeMarkBackedUpResponse { - /** - * Current onboarding state after the requested step. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } -} - -export interface RecoveryCodeVerifyResponse { - /** - * Current onboarding state after the requested step. - */ - appState: RecoveryCodeVerifyResponse.AppState; -} - -export namespace RecoveryCodeVerifyResponse { - /** - * Current onboarding state after the requested step. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } -} - -export interface RecoveryCodeVerifyParams { - /** - * Recovery key saved by the user. - */ - recoveryCode: string; -} - -RecoveryCode.Reset = Reset; -RecoveryCode.BaseReset = BaseReset; - -export declare namespace RecoveryCode { - export { - type RecoveryCodeMarkBackedUpResponse as RecoveryCodeMarkBackedUpResponse, - type RecoveryCodeVerifyResponse as RecoveryCodeVerifyResponse, - type RecoveryCodeVerifyParams as RecoveryCodeVerifyParams, - }; - - export { - Reset as Reset, - BaseReset as BaseReset, - type ResetCreateResponse as ResetCreateResponse, - type ResetConfirmResponse as ResetConfirmResponse, - type ResetCreateParams as ResetCreateParams, - type ResetConfirmParams as ResetConfirmParams, - }; -} diff --git a/src/resources/app/e2ee/verification/sas.ts b/src/resources/app/e2ee/verification/sas.ts deleted file mode 100644 index 5470c77b..00000000 --- a/src/resources/app/e2ee/verification/sas.ts +++ /dev/null @@ -1,518 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../../core/resource'; -import { APIPromise } from '../../../../core/api-promise'; -import { RequestOptions } from '../../../../internal/request-options'; -import { path } from '../../../../internal/utils/path'; - -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ -export class BaseSas extends APIResource { - static override readonly _key: readonly ['app', 'e2ee', 'verification', 'sas'] = Object.freeze([ - 'app', - 'e2ee', - 'verification', - 'sas', - ] as const); - - /** - * Confirm that the emoji or number sequence matches on both devices. - */ - confirm(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/sas/confirm`, options); - } - - /** - * Start emoji comparison for device verification. - */ - start(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/sas/start`, options); - } -} -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ -export class Sas extends BaseSas {} - -export interface SaConfirmResponse { - /** - * Current onboarding state after the requested step. - */ - appState: SaConfirmResponse.AppState; -} - -export namespace SaConfirmResponse { - /** - * Current onboarding state after the requested step. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } -} - -export interface SaStartResponse { - /** - * Current onboarding state after the requested step. - */ - appState: SaStartResponse.AppState; -} - -export namespace SaStartResponse { - /** - * Current onboarding state after the requested step. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } -} - -export declare namespace Sas { - export { type SaConfirmResponse as SaConfirmResponse, type SaStartResponse as SaStartResponse }; -} diff --git a/src/resources/app/e2ee/verification/verification.ts b/src/resources/app/e2ee/verification/verification.ts deleted file mode 100644 index 38c6f5b7..00000000 --- a/src/resources/app/e2ee/verification/verification.ts +++ /dev/null @@ -1,827 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../../core/resource'; -import * as QrAPI from './qr'; -import { BaseQr, Qr, QrConfirmScannedResponse, QrScanParams, QrScanResponse } from './qr'; -import * as SasAPI from './sas'; -import { BaseSas, SaConfirmResponse, SaStartResponse, Sas as SasAPISas } from './sas'; -import { APIPromise } from '../../../../core/api-promise'; -import { RequestOptions } from '../../../../internal/request-options'; -import { path } from '../../../../internal/utils/path'; - -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ -export class BaseVerification extends APIResource { - static override readonly _key: readonly ['app', 'e2ee', 'verification'] = Object.freeze([ - 'app', - 'e2ee', - 'verification', - ] as const); - - /** - * Start verifying this device from another signed-in device. - */ - create( - body: VerificationCreateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/v1/app/e2ee/verification', { body, ...options }); - } - - /** - * Accept an incoming device verification request. - */ - accept(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/accept`, options); - } - - /** - * Cancel an active device verification request. - */ - cancel( - verificationID: string, - body: VerificationCancelParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/cancel`, { body, ...options }); - } -} -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ -export class Verification extends BaseVerification { - qr: QrAPI.Qr = new QrAPI.Qr(this._client); - sas: SasAPI.Sas = new SasAPI.Sas(this._client); -} - -export interface VerificationCreateResponse { - /** - * Current onboarding state after starting verification. - */ - appState: VerificationCreateResponse.AppState; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID: string; -} - -export namespace VerificationCreateResponse { - /** - * Current onboarding state after starting verification. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } -} - -export interface VerificationAcceptResponse { - /** - * Current onboarding state after the requested step. - */ - appState: VerificationAcceptResponse.AppState; -} - -export namespace VerificationAcceptResponse { - /** - * Current onboarding state after the requested step. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } -} - -export interface VerificationCancelResponse { - /** - * Current onboarding state after the requested step. - */ - appState: VerificationCancelResponse.AppState; -} - -export namespace VerificationCancelResponse { - /** - * Current onboarding state after the requested step. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } -} - -export interface VerificationCreateParams { - /** - * User ID to verify. Defaults to the signed-in user. - */ - userID?: string; -} - -export interface VerificationCancelParams { - /** - * Optional cancellation code. - */ - code?: string; - - /** - * Optional user-facing cancellation reason. - */ - reason?: string; -} - -Verification.Qr = Qr; -Verification.BaseQr = BaseQr; -Verification.Sas = SasAPISas; -Verification.BaseSas = BaseSas; - -export declare namespace Verification { - export { - type VerificationCreateResponse as VerificationCreateResponse, - type VerificationAcceptResponse as VerificationAcceptResponse, - type VerificationCancelResponse as VerificationCancelResponse, - type VerificationCreateParams as VerificationCreateParams, - type VerificationCancelParams as VerificationCancelParams, - }; - - export { - Qr as Qr, - BaseQr as BaseQr, - type QrConfirmScannedResponse as QrConfirmScannedResponse, - type QrScanResponse as QrScanResponse, - type QrScanParams as QrScanParams, - }; - - export { - SasAPISas as Sas, - BaseSas as BaseSas, - type SaConfirmResponse as SaConfirmResponse, - type SaStartResponse as SaStartResponse, - }; -} diff --git a/src/resources/app/index.ts b/src/resources/app/index.ts index 22a33530..4771c1fd 100644 --- a/src/resources/app/index.ts +++ b/src/resources/app/index.ts @@ -6,12 +6,12 @@ export { type LoginRegistrationRequiredResponse, type LoginResponse, type LoginResponseOutput, - type RecoveryCodeResetResponse, - type StartVerificationResponse, - type StateMutationResponse, - type AppStatusResponse, + type RecoveryKeyResetResponse, + type SessionMutationResponse, + type Verification, + type VerificationResponse, + type AppSessionResponse, } from './app'; -export { E2ee, BaseE2ee } from './e2ee/index'; export { Login, BaseLogin, @@ -22,4 +22,15 @@ export { type LoginEmailParams, type LoginRegisterParams, type LoginResponseParams, -} from './login'; +} from './login/index'; +export { + Verifications, + BaseVerifications, + type VerificationCreateResponse, + type VerificationRetrieveResponse, + type VerificationListResponse, + type VerificationAcceptResponse, + type VerificationCancelResponse, + type VerificationCreateParams, + type VerificationCancelParams, +} from './verifications/index'; diff --git a/src/resources/app/login.ts b/src/resources/app/login.ts index ce2c7b79..88099915 100644 --- a/src/resources/app/login.ts +++ b/src/resources/app/login.ts @@ -1,766 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../../core/resource'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; - -/** - * Complete first-party Beeper app login - */ -export class BaseLogin extends APIResource { - static override readonly _key: readonly ['app', 'login'] = Object.freeze(['app', 'login'] as const); - - /** - * Send a sign-in code to the user email address. - */ - email(body: LoginEmailParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/email', { body, ...options, __security: {} }); - } - - /** - * Create a Beeper account after the user chooses a username and accepts the Terms - * of Use. - */ - register(body: LoginRegisterParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/register', { body, ...options, __security: {} }); - } - - /** - * Finish sign-in with the code sent to the user email address. If the user needs a - * new account, the response includes account creation copy and username - * suggestions. - */ - response(body: LoginResponseParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/response', { body, ...options, __security: {} }); - } - - /** - * Start a first-party Beeper Desktop sign-in session. - */ - start(options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/start', { ...options, __security: {} }); - } -} -/** - * Complete first-party Beeper app login - */ -export class Login extends BaseLogin {} - -export type LoginEmailResponse = unknown; - -export interface LoginRegisterResponse { - /** - * Current onboarding state after sign-in. - */ - appState: LoginRegisterResponse.AppState; - - /** - * Desktop API credentials for the signed-in app session. - */ - desktopAPI: LoginRegisterResponse.DesktopAPI; - - /** - * Account credentials for first-party app setup. - */ - matrix: LoginRegisterResponse.Matrix; -} - -export namespace LoginRegisterResponse { - /** - * Current onboarding state after sign-in. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } - - /** - * Desktop API credentials for the signed-in app session. - */ - export interface DesktopAPI { - /** - * Desktop API access token for this app session. - */ - accessToken: string; - - /** - * Granted Desktop API scopes. - */ - scope: 'read write'; - - /** - * Access token type. - */ - tokenType: 'Bearer'; - } - - /** - * Account credentials for first-party app setup. - */ - export interface Matrix { - /** - * Account access token. Returned once for first-party app setup. - */ - accessToken: string; - - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } -} - -export type LoginResponseResponse = LoginResponseResponse.UnionMember0 | LoginResponseResponse.UnionMember1; - -export namespace LoginResponseResponse { - export interface UnionMember0 { - /** - * Current onboarding state after sign-in. - */ - appState: UnionMember0.AppState; - - /** - * Desktop API credentials for the signed-in app session. - */ - desktopAPI: UnionMember0.DesktopAPI; - - /** - * Account credentials for first-party app setup. - */ - matrix: UnionMember0.Matrix; - } - - export namespace UnionMember0 { - /** - * Current onboarding state after sign-in. - */ - export interface AppState { - /** - * Encrypted messaging setup status. - */ - e2ee: AppState.E2ee; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppState.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppState.Verification; - } - - export namespace AppState { - /** - * Encrypted messaging setup status. - */ - export interface E2ee { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpCode: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2ee.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryCodeGeneratedAt?: number; - } - - export namespace E2ee { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryCode: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; - - /** - * Current trusted-device verification state. - */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * User ID that started verification. - */ - from?: string; - - /** - * Device that started verification. - */ - fromDevice?: string; - - /** - * Other device participating in verification. - */ - otherDevice?: string; - - /** - * QR code payload to display for verification. - */ - qrData?: string; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.Sas; - - /** - * Whether emoji comparison is available. - */ - supportsSAS?: boolean; - - /** - * Whether QR code verification is available. - */ - supportsScanQRCode?: boolean; - - /** - * Verification ID to pass in verification action paths. - */ - verificationID?: string; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface Sas { - /** - * Number sequence to compare on both devices. - */ - decimals: string; - - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - } - } - } - - /** - * Desktop API credentials for the signed-in app session. - */ - export interface DesktopAPI { - /** - * Desktop API access token for this app session. - */ - accessToken: string; - - /** - * Granted Desktop API scopes. - */ - scope: 'read write'; - - /** - * Access token type. - */ - tokenType: 'Bearer'; - } - - /** - * Account credentials for first-party app setup. - */ - export interface Matrix { - /** - * Account access token. Returned once for first-party app setup. - */ - accessToken: string; - - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - } - - export interface UnionMember1 { - /** - * Copy to display during account creation. - */ - copy: UnionMember1.Copy; - - /** - * Registration token returned by Beeper. - */ - leadToken: string; - - /** - * Indicates that the user needs to create a Beeper account. - */ - registrationRequired: true; - - /** - * Login request ID to use when creating the account. - */ - request: string; - - /** - * Suggested usernames for the new account. - */ - usernameSuggestions?: Array; - } - - export namespace UnionMember1 { - /** - * Copy to display during account creation. - */ - export interface Copy { - /** - * Submit button label. - */ - submit: 'Continue'; - - /** - * Terms and privacy notice to show before account creation. - */ - terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; - - /** - * Title for the username step. - */ - title: 'Choose your username'; - - /** - * Placeholder for the username field. - */ - usernamePlaceholder: 'Username'; - } - } -} - -export interface LoginStartResponse { - /** - * Login request ID to use in the next sign-in step. - */ - request: string; - - /** - * Available sign-in methods for this request. - */ - type: Array; -} - -export interface LoginEmailParams { - /** - * Email address to send the sign-in code to. - */ - email: string; - - /** - * Login request ID returned by the start step. - */ - request: string; -} - -export interface LoginRegisterParams { - /** - * Confirms that the user accepted the Terms of Use and acknowledged the Privacy - * Policy. - */ - acceptTerms: true; - - /** - * Registration token returned by Beeper. - */ - leadToken: string; - - /** - * Login request ID returned by the start step. - */ - request: string; - - /** - * Username selected by the user. - */ - username: string; -} - -export interface LoginResponseParams { - /** - * Login request ID returned by the start step. - */ - request: string; - - /** - * Sign-in code from the user email. - */ - response: string; -} - -export declare namespace Login { - export { - type LoginEmailResponse as LoginEmailResponse, - type LoginRegisterResponse as LoginRegisterResponse, - type LoginResponseResponse as LoginResponseResponse, - type LoginStartResponse as LoginStartResponse, - type LoginEmailParams as LoginEmailParams, - type LoginRegisterParams as LoginRegisterParams, - type LoginResponseParams as LoginResponseParams, - }; -} +export * from './login/index'; diff --git a/src/resources/app/login/index.ts b/src/resources/app/login/index.ts new file mode 100644 index 00000000..028b6329 --- /dev/null +++ b/src/resources/app/login/index.ts @@ -0,0 +1,14 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Login, + BaseLogin, + type LoginEmailResponse, + type LoginRegisterResponse, + type LoginResponseResponse, + type LoginStartResponse, + type LoginEmailParams, + type LoginRegisterParams, + type LoginResponseParams, +} from './login'; +export { Verification, BaseVerification } from './verification/index'; diff --git a/src/resources/app/login/login.ts b/src/resources/app/login/login.ts new file mode 100644 index 00000000..1238697e --- /dev/null +++ b/src/resources/app/login/login.ts @@ -0,0 +1,821 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as VerificationAPI from './verification/verification'; +import { BaseVerification, Verification as VerificationAPIVerification } from './verification/verification'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; + +/** + * Complete first-party Beeper app login + */ +export class BaseLogin extends APIResource { + static override readonly _key: readonly ['app', 'login'] = Object.freeze(['app', 'login'] as const); + + /** + * Send a sign-in code to the user email address. + */ + email(body: LoginEmailParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/email', { body, ...options, __security: {} }); + } + + /** + * Create a Beeper account after the user chooses a username and accepts the Terms + * of Use. + */ + register(body: LoginRegisterParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/register', { body, ...options, __security: {} }); + } + + /** + * Finish sign-in with the code sent to the user email address. If the user needs a + * new account, the response includes account creation copy and username + * suggestions. + */ + response(body: LoginResponseParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/response', { body, ...options, __security: {} }); + } + + /** + * Start a first-party Beeper Desktop sign-in session. + */ + start(options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/start', { ...options, __security: {} }); + } +} +/** + * Complete first-party Beeper app login + */ +export class Login extends BaseLogin { + verification: VerificationAPI.Verification = new VerificationAPI.Verification(this._client); +} + +export type LoginEmailResponse = unknown; + +export interface LoginRegisterResponse { + /** + * Desktop API credentials for the signed-in app session. + */ + desktopAPI: LoginRegisterResponse.DesktopAPI; + + /** + * Account credentials for first-party app setup. + */ + matrix: LoginRegisterResponse.Matrix; + + /** + * Current app session state after sign-in. + */ + session: LoginRegisterResponse.Session; +} + +export namespace LoginRegisterResponse { + /** + * Desktop API credentials for the signed-in app session. + */ + export interface DesktopAPI { + /** + * Desktop API access token for this app session. + */ + accessToken: string; + + /** + * Granted Desktop API scopes. + */ + scope: 'read write'; + + /** + * Access token type. + */ + tokenType: 'Bearer'; + } + + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Current app session state after sign-in. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } +} + +export type LoginResponseResponse = LoginResponseResponse.UnionMember0 | LoginResponseResponse.UnionMember1; + +export namespace LoginResponseResponse { + export interface UnionMember0 { + /** + * Desktop API credentials for the signed-in app session. + */ + desktopAPI: UnionMember0.DesktopAPI; + + /** + * Account credentials for first-party app setup. + */ + matrix: UnionMember0.Matrix; + + /** + * Current app session state after sign-in. + */ + session: UnionMember0.Session; + } + + export namespace UnionMember0 { + /** + * Desktop API credentials for the signed-in app session. + */ + export interface DesktopAPI { + /** + * Desktop API access token for this app session. + */ + accessToken: string; + + /** + * Granted Desktop API scopes. + */ + scope: 'read write'; + + /** + * Access token type. + */ + tokenType: 'Bearer'; + } + + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Current app session state after sign-in. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + } + + export interface UnionMember1 { + /** + * Copy to display during account creation. + */ + copy: UnionMember1.Copy; + + /** + * Registration token returned by Beeper. + */ + leadToken: string; + + /** + * Indicates that the user needs to create a Beeper account. + */ + registrationRequired: true; + + /** + * Login request ID to use when creating the account. + */ + request: string; + + /** + * Suggested usernames for the new account. + */ + usernameSuggestions?: Array; + } + + export namespace UnionMember1 { + /** + * Copy to display during account creation. + */ + export interface Copy { + /** + * Submit button label. + */ + submit: 'Continue'; + + /** + * Terms and privacy notice to show before account creation. + */ + terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; + + /** + * Title for the username step. + */ + title: 'Choose your username'; + + /** + * Placeholder for the username field. + */ + usernamePlaceholder: 'Username'; + } + } +} + +export interface LoginStartResponse { + /** + * Login request ID to use in the next sign-in step. + */ + request: string; + + /** + * Available sign-in methods for this request. + */ + type: Array; +} + +export interface LoginEmailParams { + /** + * Email address to send the sign-in code to. + */ + email: string; + + /** + * Login request ID returned by the start step. + */ + request: string; +} + +export interface LoginRegisterParams { + /** + * Confirms that the user accepted the Terms of Use and acknowledged the Privacy + * Policy. + */ + acceptTerms: true; + + /** + * Registration token returned by Beeper. + */ + leadToken: string; + + /** + * Login request ID returned by the start step. + */ + request: string; + + /** + * Username selected by the user. + */ + username: string; +} + +export interface LoginResponseParams { + /** + * Login request ID returned by the start step. + */ + request: string; + + /** + * Sign-in code from the user email. + */ + response: string; +} + +Login.Verification = VerificationAPIVerification; +Login.BaseVerification = BaseVerification; + +export declare namespace Login { + export { + type LoginEmailResponse as LoginEmailResponse, + type LoginRegisterResponse as LoginRegisterResponse, + type LoginResponseResponse as LoginResponseResponse, + type LoginStartResponse as LoginStartResponse, + type LoginEmailParams as LoginEmailParams, + type LoginRegisterParams as LoginRegisterParams, + type LoginResponseParams as LoginResponseParams, + }; + + export { VerificationAPIVerification as Verification, BaseVerification as BaseVerification }; +} diff --git a/src/resources/app/e2ee/verification.ts b/src/resources/app/login/verification.ts similarity index 100% rename from src/resources/app/e2ee/verification.ts rename to src/resources/app/login/verification.ts diff --git a/src/resources/app/login/verification/index.ts b/src/resources/app/login/verification/index.ts new file mode 100644 index 00000000..a24d5e5e --- /dev/null +++ b/src/resources/app/login/verification/index.ts @@ -0,0 +1,9 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + RecoveryKey, + BaseRecoveryKey, + type RecoveryKeyVerifyResponse, + type RecoveryKeyVerifyParams, +} from './recovery-key/index'; +export { Verification, BaseVerification } from './verification'; diff --git a/src/resources/app/e2ee.ts b/src/resources/app/login/verification/recovery-key.ts similarity index 69% rename from src/resources/app/e2ee.ts rename to src/resources/app/login/verification/recovery-key.ts index b8f9ae3a..670c4840 100644 --- a/src/resources/app/e2ee.ts +++ b/src/resources/app/login/verification/recovery-key.ts @@ -1,3 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './e2ee/index'; +export * from './recovery-key/index'; diff --git a/src/resources/app/e2ee/recovery-code/index.ts b/src/resources/app/login/verification/recovery-key/index.ts similarity index 59% rename from src/resources/app/e2ee/recovery-code/index.ts rename to src/resources/app/login/verification/recovery-key/index.ts index d51bd744..e0dbac2d 100644 --- a/src/resources/app/e2ee/recovery-code/index.ts +++ b/src/resources/app/login/verification/recovery-key/index.ts @@ -1,12 +1,11 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export { - RecoveryCode, - BaseRecoveryCode, - type RecoveryCodeMarkBackedUpResponse, - type RecoveryCodeVerifyResponse, - type RecoveryCodeVerifyParams, -} from './recovery-code'; + RecoveryKey, + BaseRecoveryKey, + type RecoveryKeyVerifyResponse, + type RecoveryKeyVerifyParams, +} from './recovery-key'; export { Reset, BaseReset, diff --git a/src/resources/app/login/verification/recovery-key/recovery-key.ts b/src/resources/app/login/verification/recovery-key/recovery-key.ts new file mode 100644 index 00000000..1be45f40 --- /dev/null +++ b/src/resources/app/login/verification/recovery-key/recovery-key.ts @@ -0,0 +1,327 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../../../core/resource'; +import * as ResetAPI from './reset'; +import { + BaseReset, + Reset, + ResetConfirmParams, + ResetConfirmResponse, + ResetCreateParams, + ResetCreateResponse, +} from './reset'; +import { APIPromise } from '../../../../../core/api-promise'; +import { RequestOptions } from '../../../../../internal/request-options'; + +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class BaseRecoveryKey extends APIResource { + static override readonly _key: readonly ['app', 'login', 'verification', 'recoveryKey'] = Object.freeze([ + 'app', + 'login', + 'verification', + 'recoveryKey', + ] as const); + + /** + * Unlock encrypted messages with the user recovery key. + */ + verify(body: RecoveryKeyVerifyParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/login/verification/recovery-key', { body, ...options }); + } +} +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class RecoveryKey extends BaseRecoveryKey { + reset: ResetAPI.Reset = new ResetAPI.Reset(this._client); +} + +export interface RecoveryKeyVerifyResponse { + /** + * Current app session state. + */ + session: RecoveryKeyVerifyResponse.Session; +} + +export namespace RecoveryKeyVerifyResponse { + /** + * Current app session state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } +} + +export interface RecoveryKeyVerifyParams { + /** + * Recovery key saved by the user. + */ + recoveryKey: string; +} + +RecoveryKey.Reset = Reset; +RecoveryKey.BaseReset = BaseReset; + +export declare namespace RecoveryKey { + export { + type RecoveryKeyVerifyResponse as RecoveryKeyVerifyResponse, + type RecoveryKeyVerifyParams as RecoveryKeyVerifyParams, + }; + + export { + Reset as Reset, + BaseReset as BaseReset, + type ResetCreateResponse as ResetCreateResponse, + type ResetConfirmResponse as ResetConfirmResponse, + type ResetCreateParams as ResetCreateParams, + type ResetConfirmParams as ResetConfirmParams, + }; +} diff --git a/src/resources/app/e2ee/recovery-code/reset.ts b/src/resources/app/login/verification/recovery-key/reset.ts similarity index 68% rename from src/resources/app/e2ee/recovery-code/reset.ts rename to src/resources/app/login/verification/recovery-key/reset.ts index d8e64f9b..a6ba60f7 100644 --- a/src/resources/app/e2ee/recovery-code/reset.ts +++ b/src/resources/app/login/verification/recovery-key/reset.ts @@ -1,19 +1,15 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../../../../core/resource'; -import { APIPromise } from '../../../../core/api-promise'; -import { RequestOptions } from '../../../../internal/request-options'; +import { APIResource } from '../../../../../core/resource'; +import { APIPromise } from '../../../../../core/api-promise'; +import { RequestOptions } from '../../../../../internal/request-options'; /** * First-party sign-in and encrypted messaging setup for Beeper Desktop. */ export class BaseReset extends APIResource { - static override readonly _key: readonly ['app', 'e2ee', 'recoveryCode', 'reset'] = Object.freeze([ - 'app', - 'e2ee', - 'recoveryCode', - 'reset', - ] as const); + static override readonly _key: readonly ['app', 'login', 'verification', 'recoveryKey', 'reset'] = + Object.freeze(['app', 'login', 'verification', 'recoveryKey', 'reset'] as const); /** * Create a new recovery key when the user cannot use the existing one. @@ -22,14 +18,14 @@ export class BaseReset extends APIResource { body: ResetCreateParams | null | undefined = {}, options?: RequestOptions, ): APIPromise { - return this._client.post('/v1/app/e2ee/recovery-code/reset', { body, ...options }); + return this._client.post('/v1/app/login/verification/recovery-key/reset', { body, ...options }); } /** * Confirm that the new recovery key should be used for this account. */ confirm(body: ResetConfirmParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/e2ee/recovery-code/reset/confirm', { body, ...options }); + return this._client.post('/v1/app/login/verification/recovery-key/reset/confirm', { body, ...options }); } } /** @@ -39,25 +35,25 @@ export class Reset extends BaseReset {} export interface ResetCreateResponse { /** - * Current onboarding state after creating the new recovery key. + * New recovery key. Show it once and ask the user to save it. */ - appState: ResetCreateResponse.AppState; + recoveryKey: string; /** - * New recovery key. Show it once and ask the user to save it. + * Current session state after creating the new recovery key. */ - recoveryCode: string; + session: ResetCreateResponse.Session; } export namespace ResetCreateResponse { /** - * Current onboarding state after creating the new recovery key. + * Current session state after creating the new recovery key. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -74,19 +70,19 @@ export namespace ResetCreateResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -100,7 +96,7 @@ export namespace ResetCreateResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -115,7 +111,7 @@ export namespace ResetCreateResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -130,10 +126,10 @@ export namespace ResetCreateResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -151,7 +147,7 @@ export namespace ResetCreateResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -190,61 +186,59 @@ export namespace ResetCreateResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -264,18 +258,43 @@ export namespace ResetCreateResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. */ - decimals: string; + id: string; + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } @@ -283,20 +302,20 @@ export namespace ResetCreateResponse { export interface ResetConfirmResponse { /** - * Current onboarding state after the requested step. + * Current app session state. */ - appState: ResetConfirmResponse.AppState; + session: ResetConfirmResponse.Session; } export namespace ResetConfirmResponse { /** - * Current onboarding state after the requested step. + * Current app session state. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -313,19 +332,19 @@ export namespace ResetConfirmResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -339,7 +358,7 @@ export namespace ResetConfirmResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -354,7 +373,7 @@ export namespace ResetConfirmResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -369,10 +388,10 @@ export namespace ResetConfirmResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -390,7 +409,7 @@ export namespace ResetConfirmResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -429,61 +448,59 @@ export namespace ResetConfirmResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -503,18 +520,43 @@ export namespace ResetConfirmResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. */ - decimals: string; + id: string; + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } @@ -524,14 +566,14 @@ export interface ResetCreateParams { /** * Existing recovery key, if the user has it. */ - recoveryCode?: string; + existingRecoveryKey?: string; } export interface ResetConfirmParams { /** * New recovery key returned by the reset step. */ - recoveryCode: string; + recoveryKey: string; } export declare namespace Reset { diff --git a/src/resources/app/login/verification/verification.ts b/src/resources/app/login/verification/verification.ts new file mode 100644 index 00000000..0583568a --- /dev/null +++ b/src/resources/app/login/verification/verification.ts @@ -0,0 +1,33 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../../core/resource'; +import * as RecoveryKeyAPI from './recovery-key/recovery-key'; +import { + BaseRecoveryKey, + RecoveryKey, + RecoveryKeyVerifyParams, + RecoveryKeyVerifyResponse, +} from './recovery-key/recovery-key'; + +export class BaseVerification extends APIResource { + static override readonly _key: readonly ['app', 'login', 'verification'] = Object.freeze([ + 'app', + 'login', + 'verification', + ] as const); +} +export class Verification extends BaseVerification { + recoveryKey: RecoveryKeyAPI.RecoveryKey = new RecoveryKeyAPI.RecoveryKey(this._client); +} + +Verification.RecoveryKey = RecoveryKey; +Verification.BaseRecoveryKey = BaseRecoveryKey; + +export declare namespace Verification { + export { + RecoveryKey as RecoveryKey, + BaseRecoveryKey as BaseRecoveryKey, + type RecoveryKeyVerifyResponse as RecoveryKeyVerifyResponse, + type RecoveryKeyVerifyParams as RecoveryKeyVerifyParams, + }; +} diff --git a/src/resources/matrix.ts b/src/resources/app/verifications.ts similarity index 69% rename from src/resources/matrix.ts rename to src/resources/app/verifications.ts index ee5d2cc9..6d828906 100644 --- a/src/resources/matrix.ts +++ b/src/resources/app/verifications.ts @@ -1,3 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './matrix/index'; +export * from './verifications/index'; diff --git a/src/resources/app/e2ee/verification/index.ts b/src/resources/app/verifications/index.ts similarity index 62% rename from src/resources/app/e2ee/verification/index.ts rename to src/resources/app/verifications/index.ts index 579206f3..a8a8aacb 100644 --- a/src/resources/app/e2ee/verification/index.ts +++ b/src/resources/app/verifications/index.ts @@ -1,13 +1,15 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export { Qr, BaseQr, type QrConfirmScannedResponse, type QrScanResponse, type QrScanParams } from './qr'; -export { Sas, BaseSas, type SaConfirmResponse, type SaStartResponse } from './sas'; +export { SAS, BaseSAS, type SASConfirmResponse, type SASStartResponse } from './sas'; export { - Verification, - BaseVerification, + Verifications, + BaseVerifications, type VerificationCreateResponse, + type VerificationRetrieveResponse, + type VerificationListResponse, type VerificationAcceptResponse, type VerificationCancelResponse, type VerificationCreateParams, type VerificationCancelParams, -} from './verification'; +} from './verifications'; diff --git a/src/resources/app/e2ee/verification/qr.ts b/src/resources/app/verifications/qr.ts similarity index 50% rename from src/resources/app/e2ee/verification/qr.ts rename to src/resources/app/verifications/qr.ts index dc31dfdd..c55b805b 100644 --- a/src/resources/app/e2ee/verification/qr.ts +++ b/src/resources/app/verifications/qr.ts @@ -1,18 +1,17 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../../../../core/resource'; -import { APIPromise } from '../../../../core/api-promise'; -import { RequestOptions } from '../../../../internal/request-options'; -import { path } from '../../../../internal/utils/path'; +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; /** * First-party sign-in and encrypted messaging setup for Beeper Desktop. */ export class BaseQr extends APIResource { - static override readonly _key: readonly ['app', 'e2ee', 'verification', 'qr'] = Object.freeze([ + static override readonly _key: readonly ['app', 'verifications', 'qr'] = Object.freeze([ 'app', - 'e2ee', - 'verification', + 'verifications', 'qr', ] as const); @@ -20,14 +19,14 @@ export class BaseQr extends APIResource { * Confirm that another device scanned this device QR code. */ confirmScanned(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/v1/app/e2ee/verification/${verificationID}/qr/confirm-scanned`, options); + return this._client.post(path`/v1/app/verifications/${verificationID}/qr/confirm-scanned`, options); } /** * Submit the QR code scanned from another signed-in device. */ scan(body: QrScanParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/e2ee/verification/qr/scan', { body, ...options }); + return this._client.post('/v1/app/verifications/qr/scan', { body, ...options }); } } /** @@ -37,20 +36,25 @@ export class Qr extends BaseQr {} export interface QrConfirmScannedResponse { /** - * Current onboarding state after the requested step. + * Current session state. */ - appState: QrConfirmScannedResponse.AppState; + session: QrConfirmScannedResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: QrConfirmScannedResponse.Verification; } export namespace QrConfirmScannedResponse { /** - * Current onboarding state after the requested step. + * Current session state. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -67,19 +71,19 @@ export namespace QrConfirmScannedResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -93,7 +97,7 @@ export namespace QrConfirmScannedResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -108,7 +112,7 @@ export namespace QrConfirmScannedResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -123,10 +127,10 @@ export namespace QrConfirmScannedResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -144,7 +148,7 @@ export namespace QrConfirmScannedResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -183,61 +187,59 @@ export namespace QrConfirmScannedResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -257,39 +259,186 @@ export namespace QrConfirmScannedResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. */ - decimals: string; + id: string; + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } } export interface QrScanResponse { /** - * Current onboarding state after the requested step. + * Current session state. */ - appState: QrScanResponse.AppState; + session: QrScanResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: QrScanResponse.Verification; } export namespace QrScanResponse { /** - * Current onboarding state after the requested step. + * Current session state. */ - export interface AppState { + export interface Session { /** * Encrypted messaging setup status. */ - e2ee: AppState.E2ee; + e2ee: Session.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -306,19 +455,19 @@ export namespace QrScanResponse { /** * Signed-in account details. Omitted until sign-in is complete. */ - matrix?: AppState.Matrix; + matrix?: Session.Matrix; /** * Trusted-device verification progress. */ - verification?: AppState.Verification; + verification?: Session.Verification; } - export namespace AppState { + export namespace Session { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -332,7 +481,7 @@ export namespace QrScanResponse { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -347,7 +496,7 @@ export namespace QrScanResponse { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -362,10 +511,10 @@ export namespace QrScanResponse { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -383,7 +532,7 @@ export namespace QrScanResponse { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -422,61 +571,59 @@ export namespace QrScanResponse { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -496,21 +643,163 @@ export namespace QrScanResponse { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. */ - decimals: string; + id: string; + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } } export interface QrScanParams { diff --git a/src/resources/app/verifications/sas.ts b/src/resources/app/verifications/sas.ts new file mode 100644 index 00000000..be3d4850 --- /dev/null +++ b/src/resources/app/verifications/sas.ts @@ -0,0 +1,807 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class BaseSAS extends APIResource { + static override readonly _key: readonly ['app', 'verifications', 'sas'] = Object.freeze([ + 'app', + 'verifications', + 'sas', + ] as const); + + /** + * Confirm that the emoji or number sequence matches on both devices. + */ + confirm(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/verifications/${verificationID}/sas/confirm`, options); + } + + /** + * Start emoji comparison for device verification. + */ + start(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/verifications/${verificationID}/sas/start`, options); + } +} +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop. + */ +export class SAS extends BaseSAS {} + +export interface SASConfirmResponse { + /** + * Current session state. + */ + session: SASConfirmResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: SASConfirmResponse.Verification; +} + +export namespace SASConfirmResponse { + /** + * Current session state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface SASStartResponse { + /** + * Current session state. + */ + session: SASStartResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: SASStartResponse.Verification; +} + +export namespace SASStartResponse { + /** + * Current session state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export declare namespace SAS { + export { type SASConfirmResponse as SASConfirmResponse, type SASStartResponse as SASStartResponse }; +} diff --git a/src/resources/app/verifications/verifications.ts b/src/resources/app/verifications/verifications.ts new file mode 100644 index 00000000..a9dab4cd --- /dev/null +++ b/src/resources/app/verifications/verifications.ts @@ -0,0 +1,1785 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as QrAPI from './qr'; +import { BaseQr, Qr as QrAPIQr, QrConfirmScannedResponse, QrScanParams, QrScanResponse } from './qr'; +import * as SASAPI from './sas'; +import { BaseSAS, SAS as SasapiSAS, SASConfirmResponse, SASStartResponse } from './sas'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * Manage device verification transactions + */ +export class BaseVerifications extends APIResource { + static override readonly _key: readonly ['app', 'verifications'] = Object.freeze([ + 'app', + 'verifications', + ] as const); + + /** + * Start verifying this device from another signed-in device. + */ + create( + body: VerificationCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/v1/app/verifications', { body, ...options }); + } + + /** + * Get the current state of a device verification transaction. + */ + retrieve(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/app/verifications/${verificationID}`, options); + } + + /** + * List pending and active device verification transactions. Use this to recover + * state without a websocket connection. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/v1/app/verifications', options); + } + + /** + * Accept an incoming device verification request. + */ + accept(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/verifications/${verificationID}/accept`, options); + } + + /** + * Cancel an active device verification request. + */ + cancel( + verificationID: string, + body: VerificationCancelParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/v1/app/verifications/${verificationID}/cancel`, { body, ...options }); + } +} +/** + * Manage device verification transactions + */ +export class Verifications extends BaseVerifications { + qr: QrAPI.Qr = new QrAPI.Qr(this._client); + sas: SASAPI.SAS = new SASAPI.SAS(this._client); +} + +export interface VerificationCreateResponse { + /** + * Current session state. + */ + session: VerificationCreateResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: VerificationCreateResponse.Verification; +} + +export namespace VerificationCreateResponse { + /** + * Current session state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationRetrieveResponse { + /** + * Current session state. + */ + session: VerificationRetrieveResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: VerificationRetrieveResponse.Verification; +} + +export namespace VerificationRetrieveResponse { + /** + * Current session state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationListResponse { + items: Array; +} + +export namespace VerificationListResponse { + /** + * Trusted-device verification progress. + */ + export interface Item { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Item.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Item.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Item.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Item.SAS; + } + + export namespace Item { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationAcceptResponse { + /** + * Current session state. + */ + session: VerificationAcceptResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: VerificationAcceptResponse.Verification; +} + +export namespace VerificationAcceptResponse { + /** + * Current session state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationCancelResponse { + /** + * Current session state. + */ + session: VerificationCancelResponse.Session; + + /** + * Trusted-device verification progress. + */ + verification?: VerificationCancelResponse.Verification; +} + +export namespace VerificationCancelResponse { + /** + * Current session state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current onboarding state for Beeper Desktop. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted-device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper server URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted-device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationCreateParams { + /** + * Why this verification is being started. + */ + purpose?: 'login' | 'device'; + + /** + * User ID to verify. Defaults to the signed-in user. + */ + userID?: string; +} + +export interface VerificationCancelParams { + /** + * Optional cancellation code. + */ + code?: string; + + /** + * Optional user-facing cancellation reason. + */ + reason?: string; +} + +Verifications.Qr = QrAPIQr; +Verifications.BaseQr = BaseQr; +Verifications.SAS = SasapiSAS; +Verifications.BaseSAS = BaseSAS; + +export declare namespace Verifications { + export { + type VerificationCreateResponse as VerificationCreateResponse, + type VerificationRetrieveResponse as VerificationRetrieveResponse, + type VerificationListResponse as VerificationListResponse, + type VerificationAcceptResponse as VerificationAcceptResponse, + type VerificationCancelResponse as VerificationCancelResponse, + type VerificationCreateParams as VerificationCreateParams, + type VerificationCancelParams as VerificationCancelParams, + }; + + export { + QrAPIQr as Qr, + BaseQr as BaseQr, + type QrConfirmScannedResponse as QrConfirmScannedResponse, + type QrScanResponse as QrScanResponse, + type QrScanParams as QrScanParams, + }; + + export { + SasapiSAS as SAS, + BaseSAS as BaseSAS, + type SASConfirmResponse as SASConfirmResponse, + type SASStartResponse as SASStartResponse, + }; +} diff --git a/src/resources/bridges.ts b/src/resources/bridges.ts index dc1712c2..3a874ef4 100644 --- a/src/resources/bridges.ts +++ b/src/resources/bridges.ts @@ -1,107 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { APIResource } from '../core/resource'; -import * as AccountsAPI from './accounts/accounts'; -import { APIPromise } from '../core/api-promise'; -import { RequestOptions } from '../internal/request-options'; - -/** - * Manage bridge-backed account types and account availability - */ -export class BaseBridges extends APIResource { - static override readonly _key: readonly ['bridges'] = Object.freeze(['bridges'] as const); - - /** - * List bridge-backed account types that can be shown in add-account flows, grouped - * with connected accounts that use the same Account schema as GET /v1/accounts. - */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/v1/bridges', options); - } -} -/** - * Manage bridge-backed account types and account availability - */ -export class Bridges extends BaseBridges {} - -/** - * Bridge-backed account type that can be shown in add-account flows. - */ -export interface BridgeAvailability { - /** - * Connected accounts for this bridge. Uses the same Account schema as GET - * /v1/accounts. - */ - accounts: Array; - - /** - * Number of active accounts for this network on this device. - */ - activeAccountCount: number; - - /** - * Bridge metadata for the account. Available in Beeper Desktop v4.2.785+. - */ - bridge: BridgeAvailability.Bridge; - - /** - * Human-friendly account type name shown in Beeper Desktop. - */ - displayName: string; - - /** - * Login mode used by Beeper Desktop for this bridge. - */ - loginMode: string; - - /** - * Whether this bridge can currently be used to add an account. - */ - status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable'; - - /** - * Network grouping used for account counts and limits. - */ - network?: string; - - /** - * Human-friendly status text matching Beeper Desktop account management language. - */ - statusText?: string; -} - -export namespace BridgeAvailability { - /** - * Bridge metadata for the account. Available in Beeper Desktop v4.2.785+. - */ - export interface Bridge { - /** - * Bridge instance identifier. Matrix and cloud bridges often use the bridge type - * (for example matrix or discordgo); local bridges use a local bridge ID (for - * example local-whatsapp). Available in Beeper Desktop v4.2.785+. - */ - id: string; - - /** - * Bridge provider for the account. Available in Beeper Desktop v4.2.785+. - */ - provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; - - /** - * Bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, or twitter. - * Available in Beeper Desktop v4.2.785+. - */ - type: string; - } -} - -/** - * Bridge-backed account types and their connected accounts. - */ -export interface BridgeListResponse { - items: Array; -} - -export declare namespace Bridges { - export { type BridgeAvailability as BridgeAvailability, type BridgeListResponse as BridgeListResponse }; -} +export * from './bridges/index'; diff --git a/src/resources/bridges/bridges.ts b/src/resources/bridges/bridges.ts new file mode 100644 index 00000000..c6640c32 --- /dev/null +++ b/src/resources/bridges/bridges.ts @@ -0,0 +1,510 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as BridgesAPI from './bridges'; +import * as Shared from '../shared'; +import * as AccountsAPI from '../accounts/accounts'; +import * as ConnectionsAPI from './connections'; +import { + BaseConnections, + ConnectionListResponse, + ConnectionRemoveParams, + ConnectionRemoveResponse, + ConnectionRetrieveParams, + Connections, +} from './connections'; +import * as LoginFlowsAPI from './login-flows'; +import { BaseLoginFlows, LoginFlowListResponse, LoginFlows } from './login-flows'; +import * as LoginSessionsAPI from './login-sessions/login-sessions'; +import { + BaseLoginSessions, + LoginSessionCancelParams, + LoginSessionCancelResponse, + LoginSessionCreateParams, + LoginSessionRetrieveParams, + LoginSessions, +} from './login-sessions/login-sessions'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * Manage bridge-backed account types, connections, and login sessions + */ +export class BaseBridges extends APIResource { + static override readonly _key: readonly ['bridges'] = Object.freeze(['bridges'] as const); + + /** + * Get one bridge-backed account type and the connected accounts that use it. + */ + retrieve(bridgeID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/bridges/${bridgeID}`, options); + } + + /** + * List bridge-backed account types that can be shown in add-account flows, grouped + * with connected accounts that use the same Account schema as GET /v1/accounts. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/v1/bridges', options); + } + + /** + * Get bridgev2 provisioning capabilities for a bridge. + */ + retrieveCapabilities(bridgeID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/bridges/${bridgeID}/capabilities`, options); + } +} +/** + * Manage bridge-backed account types, connections, and login sessions + */ +export class Bridges extends BaseBridges { + loginFlows: LoginFlowsAPI.LoginFlows = new LoginFlowsAPI.LoginFlows(this._client); + connections: ConnectionsAPI.Connections = new ConnectionsAPI.Connections(this._client); + loginSessions: LoginSessionsAPI.LoginSessions = new LoginSessionsAPI.LoginSessions(this._client); +} + +/** + * Bridge-backed account type that can be shown in add-account flows. + */ +export interface Bridge { + /** + * Bridge instance identifier. Use with bridge login-flow endpoints. + */ + id: string; + + /** + * Connected accounts for this bridge. Uses the same Account schema as GET + * /v1/accounts. + */ + accounts: Array; + + /** + * Number of active accounts for this network on this device. + */ + activeAccountCount: number; + + /** + * Human-friendly account type name shown in Beeper Desktop. + */ + displayName: string; + + /** + * Bridge provider. + */ + provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; + + /** + * Whether this bridge can currently be used to add an account. + */ + status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; + + /** + * Whether this bridge can have multiple active accounts for the same network. + */ + supportsMultipleAccounts: boolean; + + /** + * Bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, or twitter. + */ + type: string; + + /** + * Network grouping used for account counts and limits. + */ + network?: string; + + /** + * Human-friendly status text matching Beeper Desktop account management language. + */ + statusText?: string; +} + +/** + * Durable bridge connection identity. This is not guaranteed to be one-to-one with + * a Desktop API account. + */ +export interface BridgeConnection { + bridgeID: string; + + loginID: string; + + removeScopes: Array<'current-device' | 'all-devices'>; + + status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; + + accountIDs?: Array; + + statusText?: string; + + /** + * User the account belongs to. + */ + user?: Shared.User; +} + +export interface CookieField { + id: string; + + name?: string; + + type?: 'cookie' | 'header' | 'local_storage'; +} + +/** + * bridgev2 disappearing timer capability. + */ +export interface DisappearingTimerCapability { + types: Array<'' | 'after_read' | 'after_send'>; + + omit_empty_timer?: true; + + timers?: Array; +} + +/** + * bridgev2 group field capability. + */ +export interface GroupFieldCapability { + allowed: boolean; + + max_length?: number; + + min_length?: number; + + required?: boolean; + + /** + * bridgev2 disappearing timer capability. + */ + settings?: DisappearingTimerCapability; +} + +/** + * bridgev2 group type capabilities. + */ +export interface GroupTypeCapabilities { + type_description: string; + + /** + * bridgev2 group field capability. + */ + avatar?: GroupFieldCapability; + + /** + * bridgev2 group field capability. + */ + disappear?: GroupFieldCapability; + + /** + * bridgev2 group field capability. + */ + name?: GroupFieldCapability; + + /** + * bridgev2 group field capability. + */ + parent?: GroupFieldCapability; + + /** + * bridgev2 group field capability. + */ + participants?: GroupFieldCapability; + + /** + * bridgev2 group field capability. + */ + topic?: GroupFieldCapability; + + /** + * bridgev2 group field capability. + */ + username?: GroupFieldCapability; +} + +/** + * Bridge login flow. + */ +export interface LoginFlow { + id: string; + + description?: string; + + name?: string; +} + +export interface LoginInputField { + id: string; + + initialValue?: string; + + label?: string; + + optional?: boolean; + + placeholder?: string; + + type?: string; +} + +export interface LoginSession { + bridgeID: string; + + loginSessionID: string; + + status: + | 'waiting_for_input' + | 'waiting_for_cookies' + | 'waiting_for_display' + | 'complete' + | 'cancelled' + | 'failed'; + + /** + * A chat account added to Beeper. + */ + account?: AccountsAPI.Account; + + accountID?: string; + + /** + * Durable bridge connection identity. This is not guaranteed to be one-to-one with + * a Desktop API account. + */ + connection?: BridgeConnection; + + currentStep?: + | LoginSession.UserInput + | LoginSession.Cookies + | LoginSession.DisplayAndWait + | LoginSession.Complete; + + error?: Shared.APIError; + + loginID?: string; +} + +export namespace LoginSession { + export interface UserInput { + fields: Array; + + stepID: string; + + type: 'user_input'; + + attachments?: Array; + + instructions?: string; + } + + export interface Cookies { + fields: Array; + + stepID: string; + + type: 'cookies'; + + url: string; + + expectedFinalURLRegex?: string; + + extractJS?: string; + + instructions?: string; + + userAgent?: string; + } + + export interface DisplayAndWait { + display: DisplayAndWait.Qr | DisplayAndWait.Emoji | DisplayAndWait.Nothing; + + stepID: string; + + type: 'display_and_wait'; + + instructions?: string; + } + + export namespace DisplayAndWait { + export interface Qr { + data: string; + + type: 'qr'; + } + + export interface Emoji { + imageURL: string; + + type: 'emoji'; + } + + export interface Nothing { + type: 'nothing'; + } + } + + export interface Complete { + type: 'complete'; + + /** + * A chat account added to Beeper. + */ + account?: AccountsAPI.Account; + + /** + * Durable bridge connection identity. This is not guaranteed to be one-to-one with + * a Desktop API account. + */ + connection?: BridgesAPI.BridgeConnection; + + instructions?: string; + + stepID?: string; + } +} + +/** + * bridgev2 provisioning capabilities. + */ +export interface ProvisioningCapabilities { + group_creation: { [key: string]: GroupTypeCapabilities }; + + /** + * bridgev2 resolve_identifier capabilities. + */ + resolve_identifier: ResolveIdentifierCapabilities; + + image_pack_import?: boolean; +} + +/** + * bridgev2 resolve_identifier capabilities. + */ +export interface ResolveIdentifierCapabilities { + any_phone: boolean; + + contact_list: boolean; + + create_dm: boolean; + + lookup_email: boolean; + + lookup_phone: boolean; + + lookup_username: boolean; + + search: boolean; +} + +/** + * Bridge-backed account type that can be shown in add-account flows. + */ +export interface BridgeRetrieveResponse { + /** + * Bridge instance identifier. Use with bridge login-flow endpoints. + */ + id: string; + + /** + * Connected accounts for this bridge. Uses the same Account schema as GET + * /v1/accounts. + */ + accounts: Array; + + /** + * Number of active accounts for this network on this device. + */ + activeAccountCount: number; + + /** + * Human-friendly account type name shown in Beeper Desktop. + */ + displayName: string; + + /** + * Bridge provider. + */ + provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; + + /** + * Whether this bridge can currently be used to add an account. + */ + status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; + + /** + * Whether this bridge can have multiple active accounts for the same network. + */ + supportsMultipleAccounts: boolean; + + /** + * Bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, or twitter. + */ + type: string; + + /** + * Network grouping used for account counts and limits. + */ + network?: string; + + /** + * Human-friendly status text matching Beeper Desktop account management language. + */ + statusText?: string; +} + +/** + * Bridge-backed account types and their connected accounts. + */ +export interface BridgeListResponse { + items: Array; +} + +Bridges.LoginFlows = LoginFlows; +Bridges.BaseLoginFlows = BaseLoginFlows; +Bridges.Connections = Connections; +Bridges.BaseConnections = BaseConnections; +Bridges.LoginSessions = LoginSessions; +Bridges.BaseLoginSessions = BaseLoginSessions; + +export declare namespace Bridges { + export { + type Bridge as Bridge, + type BridgeConnection as BridgeConnection, + type CookieField as CookieField, + type DisappearingTimerCapability as DisappearingTimerCapability, + type GroupFieldCapability as GroupFieldCapability, + type GroupTypeCapabilities as GroupTypeCapabilities, + type LoginFlow as LoginFlow, + type LoginInputField as LoginInputField, + type LoginSession as LoginSession, + type ProvisioningCapabilities as ProvisioningCapabilities, + type ResolveIdentifierCapabilities as ResolveIdentifierCapabilities, + type BridgeRetrieveResponse as BridgeRetrieveResponse, + type BridgeListResponse as BridgeListResponse, + }; + + export { + LoginFlows as LoginFlows, + BaseLoginFlows as BaseLoginFlows, + type LoginFlowListResponse as LoginFlowListResponse, + }; + + export { + Connections as Connections, + BaseConnections as BaseConnections, + type ConnectionListResponse as ConnectionListResponse, + type ConnectionRemoveResponse as ConnectionRemoveResponse, + type ConnectionRetrieveParams as ConnectionRetrieveParams, + type ConnectionRemoveParams as ConnectionRemoveParams, + }; + + export { + LoginSessions as LoginSessions, + BaseLoginSessions as BaseLoginSessions, + type LoginSessionCancelResponse as LoginSessionCancelResponse, + type LoginSessionCreateParams as LoginSessionCreateParams, + type LoginSessionRetrieveParams as LoginSessionRetrieveParams, + type LoginSessionCancelParams as LoginSessionCancelParams, + }; +} diff --git a/src/resources/bridges/connections.ts b/src/resources/bridges/connections.ts new file mode 100644 index 00000000..84f3e499 --- /dev/null +++ b/src/resources/bridges/connections.ts @@ -0,0 +1,102 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as BridgesAPI from './bridges'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + */ +export class BaseConnections extends APIResource { + static override readonly _key: readonly ['bridges', 'connections'] = Object.freeze([ + 'bridges', + 'connections', + ] as const); + + /** + * Get one durable bridge connection identity. + */ + retrieve( + loginID: string, + params: ConnectionRetrieveParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID } = params; + return this._client.get(path`/v1/bridges/${bridgeID}/connections/${loginID}`, options); + } + + /** + * List durable bridge connection identities for a bridge. + */ + list(bridgeID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/bridges/${bridgeID}/connections`, options); + } + + /** + * Remove a bridge connection from this device or from all devices. + */ + remove( + loginID: string, + params: ConnectionRemoveParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, ...body } = params; + return this._client.post(path`/v1/bridges/${bridgeID}/connections/${loginID}/remove`, { + body, + ...options, + }); + } +} +/** + * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + */ +export class Connections extends BaseConnections {} + +export interface ConnectionListResponse { + items: Array; +} + +export interface ConnectionRemoveResponse { + bridgeID: string; + + loginID: string; + + /** + * Where this bridge connection should be removed. + */ + scope: 'current-device' | 'all-devices'; + + status: 'removed'; + + affectedAccountIDs?: Array; +} + +export interface ConnectionRetrieveParams { + /** + * Bridge ID. + */ + bridgeID: string; +} + +export interface ConnectionRemoveParams { + /** + * Path param: Bridge ID. + */ + bridgeID: string; + + /** + * Body param: Where this bridge connection should be removed. + */ + scope: 'current-device' | 'all-devices'; +} + +export declare namespace Connections { + export { + type ConnectionListResponse as ConnectionListResponse, + type ConnectionRemoveResponse as ConnectionRemoveResponse, + type ConnectionRetrieveParams as ConnectionRetrieveParams, + type ConnectionRemoveParams as ConnectionRemoveParams, + }; +} diff --git a/src/resources/bridges/index.ts b/src/resources/bridges/index.ts new file mode 100644 index 00000000..c416019d --- /dev/null +++ b/src/resources/bridges/index.ts @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + Bridges, + BaseBridges, + type Bridge, + type BridgeConnection, + type CookieField, + type DisappearingTimerCapability, + type GroupFieldCapability, + type GroupTypeCapabilities, + type LoginFlow, + type LoginInputField, + type LoginSession, + type ProvisioningCapabilities, + type ResolveIdentifierCapabilities, + type BridgeRetrieveResponse, + type BridgeListResponse, +} from './bridges'; +export { + Connections, + BaseConnections, + type ConnectionListResponse, + type ConnectionRemoveResponse, + type ConnectionRetrieveParams, + type ConnectionRemoveParams, +} from './connections'; +export { LoginFlows, BaseLoginFlows, type LoginFlowListResponse } from './login-flows'; +export { + LoginSessions, + BaseLoginSessions, + type LoginSessionCancelResponse, + type LoginSessionCreateParams, + type LoginSessionRetrieveParams, + type LoginSessionCancelParams, +} from './login-sessions/index'; diff --git a/src/resources/bridges/login-flows.ts b/src/resources/bridges/login-flows.ts new file mode 100644 index 00000000..e10929cb --- /dev/null +++ b/src/resources/bridges/login-flows.ts @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../core/resource'; +import * as BridgesAPI from './bridges'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; +import { path } from '../../internal/utils/path'; + +/** + * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + */ +export class BaseLoginFlows extends APIResource { + static override readonly _key: readonly ['bridges', 'loginFlows'] = Object.freeze([ + 'bridges', + 'loginFlows', + ] as const); + + /** + * List bridge login flows that can be used to start a bridge login session. + */ + list(bridgeID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/bridges/${bridgeID}/login-flows`, options); + } +} +/** + * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + */ +export class LoginFlows extends BaseLoginFlows {} + +export interface LoginFlowListResponse { + items: Array; +} + +export declare namespace LoginFlows { + export { type LoginFlowListResponse as LoginFlowListResponse }; +} diff --git a/src/resources/matrix/bridges.ts b/src/resources/bridges/login-sessions.ts similarity index 68% rename from src/resources/matrix/bridges.ts rename to src/resources/bridges/login-sessions.ts index 3a874ef4..91a3fd15 100644 --- a/src/resources/matrix/bridges.ts +++ b/src/resources/bridges/login-sessions.ts @@ -1,3 +1,3 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export * from './bridges/index'; +export * from './login-sessions/index'; diff --git a/src/resources/bridges/login-sessions/index.ts b/src/resources/bridges/login-sessions/index.ts new file mode 100644 index 00000000..bddb0048 --- /dev/null +++ b/src/resources/bridges/login-sessions/index.ts @@ -0,0 +1,11 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export { + LoginSessions, + BaseLoginSessions, + type LoginSessionCancelResponse, + type LoginSessionCreateParams, + type LoginSessionRetrieveParams, + type LoginSessionCancelParams, +} from './login-sessions'; +export { Steps, BaseSteps, type StepSubmitParams } from './steps'; diff --git a/src/resources/bridges/login-sessions/login-sessions.ts b/src/resources/bridges/login-sessions/login-sessions.ts new file mode 100644 index 00000000..3297f59e --- /dev/null +++ b/src/resources/bridges/login-sessions/login-sessions.ts @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as BridgesAPI from '../bridges'; +import * as StepsAPI from './steps'; +import { BaseSteps, StepSubmitParams, Steps } from './steps'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + */ +export class BaseLoginSessions extends APIResource { + static override readonly _key: readonly ['bridges', 'loginSessions'] = Object.freeze([ + 'bridges', + 'loginSessions', + ] as const); + + /** + * Start an add-account or reconnect flow for a bridge. Omit loginID/accountID to + * add a new account. + */ + create( + bridgeID: string, + body: LoginSessionCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/v1/bridges/${bridgeID}/login-sessions`, { body, ...options }); + } + + /** + * Get the current state of a temporary bridge login session. + */ + retrieve( + loginSessionID: string, + params: LoginSessionRetrieveParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID } = params; + return this._client.get(path`/v1/bridges/${bridgeID}/login-sessions/${loginSessionID}`, options); + } + + /** + * Cancel a temporary bridge login session. + */ + cancel( + loginSessionID: string, + params: LoginSessionCancelParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID } = params; + return this._client.delete(path`/v1/bridges/${bridgeID}/login-sessions/${loginSessionID}`, options); + } +} +/** + * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + */ +export class LoginSessions extends BaseLoginSessions { + steps: StepsAPI.Steps = new StepsAPI.Steps(this._client); +} + +export interface LoginSessionCancelResponse { + bridgeID: string; + + loginSessionID: string; + + status: 'cancelled'; +} + +export interface LoginSessionCreateParams { + accountID?: string; + + flowID?: string; + + loginID?: string; +} + +export interface LoginSessionRetrieveParams { + /** + * Bridge ID. + */ + bridgeID: string; +} + +export interface LoginSessionCancelParams { + /** + * Bridge ID. + */ + bridgeID: string; +} + +LoginSessions.Steps = Steps; +LoginSessions.BaseSteps = BaseSteps; + +export declare namespace LoginSessions { + export { + type LoginSessionCancelResponse as LoginSessionCancelResponse, + type LoginSessionCreateParams as LoginSessionCreateParams, + type LoginSessionRetrieveParams as LoginSessionRetrieveParams, + type LoginSessionCancelParams as LoginSessionCancelParams, + }; + + export { Steps as Steps, BaseSteps as BaseSteps, type StepSubmitParams as StepSubmitParams }; +} diff --git a/src/resources/bridges/login-sessions/steps.ts b/src/resources/bridges/login-sessions/steps.ts new file mode 100644 index 00000000..b05938fe --- /dev/null +++ b/src/resources/bridges/login-sessions/steps.ts @@ -0,0 +1,73 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { APIResource } from '../../../core/resource'; +import * as BridgesAPI from '../bridges'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; + +/** + * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + */ +export class BaseSteps extends APIResource { + static override readonly _key: readonly ['bridges', 'loginSessions', 'steps'] = Object.freeze([ + 'bridges', + 'loginSessions', + 'steps', + ] as const); + + /** + * Submit input for the current step of a bridge login session. + */ + submit( + stepID: string, + params: StepSubmitParams, + options?: RequestOptions, + ): APIPromise { + const { bridgeID, loginSessionID, ...body } = params; + return this._client.post(path`/v1/bridges/${bridgeID}/login-sessions/${loginSessionID}/steps/${stepID}`, { + body, + ...options, + }); + } +} +/** + * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + */ +export class Steps extends BaseSteps {} + +export interface StepSubmitParams { + /** + * Path param: Bridge ID. + */ + bridgeID: string; + + /** + * Path param: Temporary bridge login session ID. + */ + loginSessionID: string; + + /** + * Body param + */ + type: 'user_input' | 'cookies' | 'display_and_wait'; + + /** + * Body param + */ + fields?: { [key: string]: string }; + + /** + * Body param + */ + lastURL?: string; + + /** + * Body param + */ + source?: 'api' | 'webview' | 'browser_extension'; +} + +export declare namespace Steps { + export { type StepSubmitParams as StepSubmitParams }; +} diff --git a/src/resources/index.ts b/src/resources/index.ts index 7f48ccbe..6ab15bb4 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,17 +1,25 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. export * from './shared'; -export { Accounts, BaseAccounts, type Account, type AccountListResponse } from './accounts/accounts'; +export { + Accounts, + BaseAccounts, + type Account, + type AccountBridge, + type AccountRetrieveResponse, + type AccountListResponse, +} from './accounts/accounts'; export { App, BaseApp, type LoginRegistrationRequiredResponse, type LoginResponse, type LoginResponseOutput, - type RecoveryCodeResetResponse, - type StartVerificationResponse, - type StateMutationResponse, - type AppStatusResponse, + type RecoveryKeyResetResponse, + type SessionMutationResponse, + type Verification, + type VerificationResponse, + type AppSessionResponse, } from './app/app'; export { Assets, @@ -24,7 +32,23 @@ export { type AssetUploadParams, type AssetUploadBase64Params, } from './assets'; -export { Bridges, BaseBridges, type BridgeAvailability, type BridgeListResponse } from './bridges'; +export { + Bridges, + BaseBridges, + type Bridge, + type BridgeConnection, + type CookieField, + type DisappearingTimerCapability, + type GroupFieldCapability, + type GroupTypeCapabilities, + type LoginFlow, + type LoginInputField, + type LoginSession, + type ProvisioningCapabilities, + type ResolveIdentifierCapabilities, + type BridgeRetrieveResponse, + type BridgeListResponse, +} from './bridges/bridges'; export { Chats, BaseChats, @@ -46,7 +70,6 @@ export { type ChatsCursorSearch, } from './chats/chats'; export { Info, BaseInfo, type InfoRetrieveResponse } from './info'; -export { Matrix, BaseMatrix } from './matrix/matrix'; export { Messages, BaseMessages, diff --git a/src/resources/matrix/bridges/auth.ts b/src/resources/matrix/bridges/auth.ts deleted file mode 100644 index 5d98374c..00000000 --- a/src/resources/matrix/bridges/auth.ts +++ /dev/null @@ -1,1950 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class BaseAuth extends APIResource { - static override readonly _key: readonly ['matrix', 'bridges', 'auth'] = Object.freeze([ - 'matrix', - 'bridges', - 'auth', - ] as const); - - /** - * Get the available login flows. - * - * @example - * ```ts - * const response = await client.matrix.bridges.auth.listFlows( - * 'bridgeID', - * ); - * ``` - */ - listFlows(bridgeID: string, options?: RequestOptions): APIPromise { - return this._client.get( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/flows`, - options, - ); - } - - /** - * Get the login IDs of the current user. - * - * @example - * ```ts - * const response = - * await client.matrix.bridges.auth.listLogins('bridgeID'); - * ``` - */ - listLogins(bridgeID: string, options?: RequestOptions): APIPromise { - return this._client.get( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/logins`, - options, - ); - } - - /** - * Log out of an existing login. - * - * @example - * ```ts - * const response = await client.matrix.bridges.auth.logout( - * 'bcc68892-b180-414f-9516-b4aadf7d0496', - * { bridgeID: 'bridgeID' }, - * ); - * ``` - */ - logout(loginID: string, params: AuthLogoutParams, options?: RequestOptions): APIPromise { - const { bridgeID } = params; - return this._client.post( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/logout/${loginID}`, - options, - ); - } - - /** - * This endpoint starts a new login process, which is used to log into the bridge. - * - * The basic flow of the entire login, including calling this endpoint, is: - * - * 1. Call `GET /v3/login/flows` to get the list of available flows. If there's - * more than one flow, ask the user to pick which one they want to use. - * 2. Call this endpoint with the chosen flow ID to start the login. The first - * login step will be returned. - * 3. Render the information provided in the step. - * 4. Call the `/login/step/...` endpoint corresponding to the step type: - * - For `user_input` and `cookies`, acquire the requested fields before calling - * the endpoint. - * - For `display_and_wait`, call the endpoint immediately (as there's nothing - * to acquire on the client side). - * 5. Handle the data returned by the login step endpoint: - * - If an error is returned, the login has failed and must be restarted (from - * either step 1 or step 2) if the user wants to try again. - * - If step type `complete` is returned, the login finished successfully. - * - Otherwise, go to step 3 with the new data. - * - * @example - * ```ts - * const response = - * await client.matrix.bridges.auth.startLogin('qr', { - * bridgeID: 'bridgeID', - * }); - * ``` - */ - startLogin( - flowID: string, - params: AuthStartLoginParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID, login_id } = params; - return this._client.post( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/start/${flowID}`, - { query: { login_id }, ...options }, - ); - } - - /** - * Submit extracted cookies in a login process. - * - * @example - * ```ts - * const response = - * await client.matrix.bridges.auth.submitCookies('stepID', { - * bridgeID: 'bridgeID', - * loginProcessID: 'loginProcessID', - * body: { foo: 'string' }, - * }); - * ``` - */ - submitCookies( - stepID: string, - params: AuthSubmitCookiesParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID, loginProcessID, body } = params; - return this._client.post( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/step/${loginProcessID}/${stepID}/cookies`, - { body: body, ...options }, - ); - } - - /** - * Submit user input in a login process. - * - * @example - * ```ts - * const response = - * await client.matrix.bridges.auth.submitUserInput( - * 'stepID', - * { - * bridgeID: 'bridgeID', - * loginProcessID: 'loginProcessID', - * body: { foo: 'string' }, - * }, - * ); - * ``` - */ - submitUserInput( - stepID: string, - params: AuthSubmitUserInputParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID, loginProcessID, body } = params; - return this._client.post( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/step/${loginProcessID}/${stepID}/user_input`, - { body: body, ...options }, - ); - } - - /** - * Wait for the next step after displaying data to the user. - * - * @example - * ```ts - * const response = - * await client.matrix.bridges.auth.waitForStep('stepID', { - * bridgeID: 'bridgeID', - * loginProcessID: 'loginProcessID', - * }); - * ``` - */ - waitForStep( - stepID: string, - params: AuthWaitForStepParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID, loginProcessID } = params; - return this._client.post( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/login/step/${loginProcessID}/${stepID}/display_and_wait`, - options, - ); - } - - /** - * Get all info that is useful for presenting this bridge in a manager interface. - * - * - Server details: remote network details, available login flows, homeserver - * name, bridge bot user ID, command prefix - * - User details: management room ID, list of logins with current state and info - * - * @example - * ```ts - * const response = await client.matrix.bridges.auth.whoami( - * 'bridgeID', - * ); - * ``` - */ - whoami(bridgeID: string, options?: RequestOptions): APIPromise { - return this._client.get( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/whoami`, - options, - ); - } -} -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class Auth extends BaseAuth {} - -export interface AuthListFlowsResponse { - flows?: Array; -} - -export namespace AuthListFlowsResponse { - /** - * An individual login flow which can be used to sign into the remote network. - */ - export interface Flow { - /** - * An internal ID that is passed to the /login/start call to start a login with - * this flow. - */ - id: string; - - /** - * A human-readable description of the login flow. - */ - description: string; - - /** - * A human-readable name for the login flow. - */ - name: string; - } -} - -export interface AuthListLoginsResponse { - login_ids?: Array; -} - -/** - * Empty object - */ -export type AuthLogoutResponse = unknown; - -/** - * A step in a login process. - */ -export type AuthStartLoginResponse = - | AuthStartLoginResponse.UnionMember0 - | AuthStartLoginResponse.UnionMember1 - | AuthStartLoginResponse.UnionMember2 - | AuthStartLoginResponse.UnionMember3; - -export namespace AuthStartLoginResponse { - /** - * Display and wait login step - */ - export interface UnionMember0 { - /** - * Parameters for the display and wait login step - */ - display_and_wait: UnionMember0.DisplayAndWait; - - type: 'display_and_wait'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember0 { - /** - * Parameters for the display and wait login step - */ - export interface DisplayAndWait { - /** - * The type of thing to display - */ - type: 'qr' | 'emoji' | 'code' | 'nothing'; - - /** - * The thing to display (raw data for QR, unicode emoji for emoji, plain string for - * code) - */ - data?: string; - - /** - * An image containing the thing to display. If present, this is recommended over - * using data directly. For emojis, the URL to the canonical image representation - * of the emoji - */ - image_url?: string; - } - } - - /** - * User input login step - */ - export interface UnionMember1 { - type: 'user_input'; - - /** - * Parameters for the user input login step - */ - user_input: UnionMember1.UserInput; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember1 { - /** - * Parameters for the user input login step - */ - export interface UserInput { - /** - * The list of fields that the user is requested to fill. - */ - fields: Array; - - /** - * A list of media attachments to show the user alongside the form fields. - */ - attachments?: Array; - } - - export namespace UserInput { - /** - * A field that the user can fill. - */ - export interface Field { - /** - * The internal ID of the field. This must be used as the key in the object when - * submitting the data back to the bridge. - */ - id: string; - - /** - * The name of the field shown to the user. - */ - name: string; - - /** - * The type of field. - */ - type: - | 'username' - | 'phone_number' - | 'email' - | 'password' - | '2fa_code' - | 'token' - | 'url' - | 'domain' - | 'select'; - - /** - * A default value that the client can pre-fill the field with. - */ - default_value?: string; - - /** - * A more detailed description of the field shown to the user. - */ - description?: string; - - /** - * For fields of type select, the valid options. - */ - options?: Array; - - /** - * A regular expression that the field value must match. - */ - pattern?: string; - } - - /** - * A media attachment to show the user. - */ - export interface Attachment { - /** - * The raw file content for the attachment encoded in base64. - */ - content: string; - - /** - * The filename for the media attachment. - */ - filename: string; - - /** - * The type of media attachment, using the same media type identifiers as Matrix - * attachments. Only some are supported. - */ - type: 'm.image' | 'm.audio'; - - /** - * Optional but recommended metadata for the attachment. Can generally be derived - * from the raw content if omitted. - */ - info?: Attachment.Info; - } - - export namespace Attachment { - /** - * Optional but recommended metadata for the attachment. Can generally be derived - * from the raw content if omitted. - */ - export interface Info { - /** - * The height of the media in pixels. Only applicable for images and videos. - */ - h?: number; - - /** - * The MIME type for the media content. - */ - mimetype?: string; - - /** - * The size of the media content in number of bytes. Strongly recommended to - * include. - */ - size?: number; - - /** - * The width of the media in pixels. Only applicable for images and videos. - */ - w?: number; - } - } - } - } - - /** - * Cookie login step - */ - export interface UnionMember2 { - /** - * Parameters for the cookie login step - */ - cookies: UnionMember2.Cookies; - - type: 'cookies'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember2 { - /** - * Parameters for the cookie login step - */ - export interface Cookies { - /** - * The list of cookies or other stored data that must be extracted. - */ - fields: Array; - - /** - * The URL to open when using a webview to extract cookies. - */ - url: string; - - /** - * A JavaScript snippet that can extract some or all of the fields. The snippet - * will evaluate to a promise that resolves when the relevant fields are found. - * Fields that are not present in the promise result must be extracted another way. - */ - extract_js?: string; - - /** - * An optional user agent that the webview should use. - */ - user_agent?: string; - - /** - * A regex pattern that the URL should match before the client closes the webview. - * - * The client may submit the login if the user closes the webview after all cookies - * are collected even if this URL is not reached, but it should only automatically - * close the webview after both cookies and the URL match. - */ - wait_for_url_pattern?: string; - } - - export namespace Cookies { - /** - * An individual cookie or other stored data item that must be extracted. - */ - export interface Field { - /** - * The name of the item to extract. - */ - name: string; - - /** - * The type of data to extract. - */ - type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; - - /** - * For the `cookie` type, the domain of the cookie. - */ - cookie_domain?: string; - - /** - * For the `request_header` and `request_body` types, a regex that matches the URLs - * from which the values can be extracted. - */ - request_url_regex?: string; - } - } - } - - /** - * Login complete - */ - export interface UnionMember3 { - /** - * Information about the completed login - */ - complete: UnionMember3.Complete; - - type: 'complete'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember3 { - /** - * Information about the completed login - */ - export interface Complete { - /** - * The unique ID of a login. Defined by the network connector. - */ - user_login_id?: string; - } - } -} - -/** - * A step in a login process. - */ -export type AuthSubmitCookiesResponse = - | AuthSubmitCookiesResponse.UnionMember0 - | AuthSubmitCookiesResponse.UnionMember1 - | AuthSubmitCookiesResponse.UnionMember2 - | AuthSubmitCookiesResponse.UnionMember3; - -export namespace AuthSubmitCookiesResponse { - /** - * Display and wait login step - */ - export interface UnionMember0 { - /** - * Parameters for the display and wait login step - */ - display_and_wait: UnionMember0.DisplayAndWait; - - type: 'display_and_wait'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember0 { - /** - * Parameters for the display and wait login step - */ - export interface DisplayAndWait { - /** - * The type of thing to display - */ - type: 'qr' | 'emoji' | 'code' | 'nothing'; - - /** - * The thing to display (raw data for QR, unicode emoji for emoji, plain string for - * code) - */ - data?: string; - - /** - * An image containing the thing to display. If present, this is recommended over - * using data directly. For emojis, the URL to the canonical image representation - * of the emoji - */ - image_url?: string; - } - } - - /** - * User input login step - */ - export interface UnionMember1 { - type: 'user_input'; - - /** - * Parameters for the user input login step - */ - user_input: UnionMember1.UserInput; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember1 { - /** - * Parameters for the user input login step - */ - export interface UserInput { - /** - * The list of fields that the user is requested to fill. - */ - fields: Array; - - /** - * A list of media attachments to show the user alongside the form fields. - */ - attachments?: Array; - } - - export namespace UserInput { - /** - * A field that the user can fill. - */ - export interface Field { - /** - * The internal ID of the field. This must be used as the key in the object when - * submitting the data back to the bridge. - */ - id: string; - - /** - * The name of the field shown to the user. - */ - name: string; - - /** - * The type of field. - */ - type: - | 'username' - | 'phone_number' - | 'email' - | 'password' - | '2fa_code' - | 'token' - | 'url' - | 'domain' - | 'select'; - - /** - * A default value that the client can pre-fill the field with. - */ - default_value?: string; - - /** - * A more detailed description of the field shown to the user. - */ - description?: string; - - /** - * For fields of type select, the valid options. - */ - options?: Array; - - /** - * A regular expression that the field value must match. - */ - pattern?: string; - } - - /** - * A media attachment to show the user. - */ - export interface Attachment { - /** - * The raw file content for the attachment encoded in base64. - */ - content: string; - - /** - * The filename for the media attachment. - */ - filename: string; - - /** - * The type of media attachment, using the same media type identifiers as Matrix - * attachments. Only some are supported. - */ - type: 'm.image' | 'm.audio'; - - /** - * Optional but recommended metadata for the attachment. Can generally be derived - * from the raw content if omitted. - */ - info?: Attachment.Info; - } - - export namespace Attachment { - /** - * Optional but recommended metadata for the attachment. Can generally be derived - * from the raw content if omitted. - */ - export interface Info { - /** - * The height of the media in pixels. Only applicable for images and videos. - */ - h?: number; - - /** - * The MIME type for the media content. - */ - mimetype?: string; - - /** - * The size of the media content in number of bytes. Strongly recommended to - * include. - */ - size?: number; - - /** - * The width of the media in pixels. Only applicable for images and videos. - */ - w?: number; - } - } - } - } - - /** - * Cookie login step - */ - export interface UnionMember2 { - /** - * Parameters for the cookie login step - */ - cookies: UnionMember2.Cookies; - - type: 'cookies'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember2 { - /** - * Parameters for the cookie login step - */ - export interface Cookies { - /** - * The list of cookies or other stored data that must be extracted. - */ - fields: Array; - - /** - * The URL to open when using a webview to extract cookies. - */ - url: string; - - /** - * A JavaScript snippet that can extract some or all of the fields. The snippet - * will evaluate to a promise that resolves when the relevant fields are found. - * Fields that are not present in the promise result must be extracted another way. - */ - extract_js?: string; - - /** - * An optional user agent that the webview should use. - */ - user_agent?: string; - - /** - * A regex pattern that the URL should match before the client closes the webview. - * - * The client may submit the login if the user closes the webview after all cookies - * are collected even if this URL is not reached, but it should only automatically - * close the webview after both cookies and the URL match. - */ - wait_for_url_pattern?: string; - } - - export namespace Cookies { - /** - * An individual cookie or other stored data item that must be extracted. - */ - export interface Field { - /** - * The name of the item to extract. - */ - name: string; - - /** - * The type of data to extract. - */ - type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; - - /** - * For the `cookie` type, the domain of the cookie. - */ - cookie_domain?: string; - - /** - * For the `request_header` and `request_body` types, a regex that matches the URLs - * from which the values can be extracted. - */ - request_url_regex?: string; - } - } - } - - /** - * Login complete - */ - export interface UnionMember3 { - /** - * Information about the completed login - */ - complete: UnionMember3.Complete; - - type: 'complete'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember3 { - /** - * Information about the completed login - */ - export interface Complete { - /** - * The unique ID of a login. Defined by the network connector. - */ - user_login_id?: string; - } - } -} - -/** - * A step in a login process. - */ -export type AuthSubmitUserInputResponse = - | AuthSubmitUserInputResponse.UnionMember0 - | AuthSubmitUserInputResponse.UnionMember1 - | AuthSubmitUserInputResponse.UnionMember2 - | AuthSubmitUserInputResponse.UnionMember3; - -export namespace AuthSubmitUserInputResponse { - /** - * Display and wait login step - */ - export interface UnionMember0 { - /** - * Parameters for the display and wait login step - */ - display_and_wait: UnionMember0.DisplayAndWait; - - type: 'display_and_wait'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember0 { - /** - * Parameters for the display and wait login step - */ - export interface DisplayAndWait { - /** - * The type of thing to display - */ - type: 'qr' | 'emoji' | 'code' | 'nothing'; - - /** - * The thing to display (raw data for QR, unicode emoji for emoji, plain string for - * code) - */ - data?: string; - - /** - * An image containing the thing to display. If present, this is recommended over - * using data directly. For emojis, the URL to the canonical image representation - * of the emoji - */ - image_url?: string; - } - } - - /** - * User input login step - */ - export interface UnionMember1 { - type: 'user_input'; - - /** - * Parameters for the user input login step - */ - user_input: UnionMember1.UserInput; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember1 { - /** - * Parameters for the user input login step - */ - export interface UserInput { - /** - * The list of fields that the user is requested to fill. - */ - fields: Array; - - /** - * A list of media attachments to show the user alongside the form fields. - */ - attachments?: Array; - } - - export namespace UserInput { - /** - * A field that the user can fill. - */ - export interface Field { - /** - * The internal ID of the field. This must be used as the key in the object when - * submitting the data back to the bridge. - */ - id: string; - - /** - * The name of the field shown to the user. - */ - name: string; - - /** - * The type of field. - */ - type: - | 'username' - | 'phone_number' - | 'email' - | 'password' - | '2fa_code' - | 'token' - | 'url' - | 'domain' - | 'select'; - - /** - * A default value that the client can pre-fill the field with. - */ - default_value?: string; - - /** - * A more detailed description of the field shown to the user. - */ - description?: string; - - /** - * For fields of type select, the valid options. - */ - options?: Array; - - /** - * A regular expression that the field value must match. - */ - pattern?: string; - } - - /** - * A media attachment to show the user. - */ - export interface Attachment { - /** - * The raw file content for the attachment encoded in base64. - */ - content: string; - - /** - * The filename for the media attachment. - */ - filename: string; - - /** - * The type of media attachment, using the same media type identifiers as Matrix - * attachments. Only some are supported. - */ - type: 'm.image' | 'm.audio'; - - /** - * Optional but recommended metadata for the attachment. Can generally be derived - * from the raw content if omitted. - */ - info?: Attachment.Info; - } - - export namespace Attachment { - /** - * Optional but recommended metadata for the attachment. Can generally be derived - * from the raw content if omitted. - */ - export interface Info { - /** - * The height of the media in pixels. Only applicable for images and videos. - */ - h?: number; - - /** - * The MIME type for the media content. - */ - mimetype?: string; - - /** - * The size of the media content in number of bytes. Strongly recommended to - * include. - */ - size?: number; - - /** - * The width of the media in pixels. Only applicable for images and videos. - */ - w?: number; - } - } - } - } - - /** - * Cookie login step - */ - export interface UnionMember2 { - /** - * Parameters for the cookie login step - */ - cookies: UnionMember2.Cookies; - - type: 'cookies'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember2 { - /** - * Parameters for the cookie login step - */ - export interface Cookies { - /** - * The list of cookies or other stored data that must be extracted. - */ - fields: Array; - - /** - * The URL to open when using a webview to extract cookies. - */ - url: string; - - /** - * A JavaScript snippet that can extract some or all of the fields. The snippet - * will evaluate to a promise that resolves when the relevant fields are found. - * Fields that are not present in the promise result must be extracted another way. - */ - extract_js?: string; - - /** - * An optional user agent that the webview should use. - */ - user_agent?: string; - - /** - * A regex pattern that the URL should match before the client closes the webview. - * - * The client may submit the login if the user closes the webview after all cookies - * are collected even if this URL is not reached, but it should only automatically - * close the webview after both cookies and the URL match. - */ - wait_for_url_pattern?: string; - } - - export namespace Cookies { - /** - * An individual cookie or other stored data item that must be extracted. - */ - export interface Field { - /** - * The name of the item to extract. - */ - name: string; - - /** - * The type of data to extract. - */ - type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; - - /** - * For the `cookie` type, the domain of the cookie. - */ - cookie_domain?: string; - - /** - * For the `request_header` and `request_body` types, a regex that matches the URLs - * from which the values can be extracted. - */ - request_url_regex?: string; - } - } - } - - /** - * Login complete - */ - export interface UnionMember3 { - /** - * Information about the completed login - */ - complete: UnionMember3.Complete; - - type: 'complete'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember3 { - /** - * Information about the completed login - */ - export interface Complete { - /** - * The unique ID of a login. Defined by the network connector. - */ - user_login_id?: string; - } - } -} - -/** - * A step in a login process. - */ -export type AuthWaitForStepResponse = - | AuthWaitForStepResponse.UnionMember0 - | AuthWaitForStepResponse.UnionMember1 - | AuthWaitForStepResponse.UnionMember2 - | AuthWaitForStepResponse.UnionMember3; - -export namespace AuthWaitForStepResponse { - /** - * Display and wait login step - */ - export interface UnionMember0 { - /** - * Parameters for the display and wait login step - */ - display_and_wait: UnionMember0.DisplayAndWait; - - type: 'display_and_wait'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember0 { - /** - * Parameters for the display and wait login step - */ - export interface DisplayAndWait { - /** - * The type of thing to display - */ - type: 'qr' | 'emoji' | 'code' | 'nothing'; - - /** - * The thing to display (raw data for QR, unicode emoji for emoji, plain string for - * code) - */ - data?: string; - - /** - * An image containing the thing to display. If present, this is recommended over - * using data directly. For emojis, the URL to the canonical image representation - * of the emoji - */ - image_url?: string; - } - } - - /** - * User input login step - */ - export interface UnionMember1 { - type: 'user_input'; - - /** - * Parameters for the user input login step - */ - user_input: UnionMember1.UserInput; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember1 { - /** - * Parameters for the user input login step - */ - export interface UserInput { - /** - * The list of fields that the user is requested to fill. - */ - fields: Array; - - /** - * A list of media attachments to show the user alongside the form fields. - */ - attachments?: Array; - } - - export namespace UserInput { - /** - * A field that the user can fill. - */ - export interface Field { - /** - * The internal ID of the field. This must be used as the key in the object when - * submitting the data back to the bridge. - */ - id: string; - - /** - * The name of the field shown to the user. - */ - name: string; - - /** - * The type of field. - */ - type: - | 'username' - | 'phone_number' - | 'email' - | 'password' - | '2fa_code' - | 'token' - | 'url' - | 'domain' - | 'select'; - - /** - * A default value that the client can pre-fill the field with. - */ - default_value?: string; - - /** - * A more detailed description of the field shown to the user. - */ - description?: string; - - /** - * For fields of type select, the valid options. - */ - options?: Array; - - /** - * A regular expression that the field value must match. - */ - pattern?: string; - } - - /** - * A media attachment to show the user. - */ - export interface Attachment { - /** - * The raw file content for the attachment encoded in base64. - */ - content: string; - - /** - * The filename for the media attachment. - */ - filename: string; - - /** - * The type of media attachment, using the same media type identifiers as Matrix - * attachments. Only some are supported. - */ - type: 'm.image' | 'm.audio'; - - /** - * Optional but recommended metadata for the attachment. Can generally be derived - * from the raw content if omitted. - */ - info?: Attachment.Info; - } - - export namespace Attachment { - /** - * Optional but recommended metadata for the attachment. Can generally be derived - * from the raw content if omitted. - */ - export interface Info { - /** - * The height of the media in pixels. Only applicable for images and videos. - */ - h?: number; - - /** - * The MIME type for the media content. - */ - mimetype?: string; - - /** - * The size of the media content in number of bytes. Strongly recommended to - * include. - */ - size?: number; - - /** - * The width of the media in pixels. Only applicable for images and videos. - */ - w?: number; - } - } - } - } - - /** - * Cookie login step - */ - export interface UnionMember2 { - /** - * Parameters for the cookie login step - */ - cookies: UnionMember2.Cookies; - - type: 'cookies'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember2 { - /** - * Parameters for the cookie login step - */ - export interface Cookies { - /** - * The list of cookies or other stored data that must be extracted. - */ - fields: Array; - - /** - * The URL to open when using a webview to extract cookies. - */ - url: string; - - /** - * A JavaScript snippet that can extract some or all of the fields. The snippet - * will evaluate to a promise that resolves when the relevant fields are found. - * Fields that are not present in the promise result must be extracted another way. - */ - extract_js?: string; - - /** - * An optional user agent that the webview should use. - */ - user_agent?: string; - - /** - * A regex pattern that the URL should match before the client closes the webview. - * - * The client may submit the login if the user closes the webview after all cookies - * are collected even if this URL is not reached, but it should only automatically - * close the webview after both cookies and the URL match. - */ - wait_for_url_pattern?: string; - } - - export namespace Cookies { - /** - * An individual cookie or other stored data item that must be extracted. - */ - export interface Field { - /** - * The name of the item to extract. - */ - name: string; - - /** - * The type of data to extract. - */ - type: 'cookie' | 'local_storage' | 'request_header' | 'request_body' | 'special'; - - /** - * For the `cookie` type, the domain of the cookie. - */ - cookie_domain?: string; - - /** - * For the `request_header` and `request_body` types, a regex that matches the URLs - * from which the values can be extracted. - */ - request_url_regex?: string; - } - } - } - - /** - * Login complete - */ - export interface UnionMember3 { - /** - * Information about the completed login - */ - complete: UnionMember3.Complete; - - type: 'complete'; - - /** - * Human-readable instructions for completing this login step. - */ - instructions?: string; - - /** - * An identifier for the current login process. Must be passed to execute more - * steps of the login. - */ - login_id?: string; - - /** - * An unique ID identifying this step. This can be used to implement special - * behavior in clients. - */ - step_id?: string; - } - - export namespace UnionMember3 { - /** - * Information about the completed login - */ - export interface Complete { - /** - * The unique ID of a login. Defined by the network connector. - */ - user_login_id?: string; - } - } -} - -/** - * Info about the bridge and user - */ -export interface AuthWhoamiResponse { - /** - * The Matrix user ID of the bridge bot. - */ - bridge_bot: string; - - /** - * The command prefix used by this bridge. - */ - command_prefix: string; - - /** - * The server name the bridge is running on. - */ - homeserver: string; - - /** - * The login flows that the bridge supports. - */ - login_flows: Array; - - /** - * The logins of the user who made the /whoami call - */ - logins: Array; - - /** - * Info about the network that the bridge is bridging to. - */ - network: AuthWhoamiResponse.Network; - - /** - * The Matrix management room ID of the user who made the /whoami call. - */ - management_room?: string; -} - -export namespace AuthWhoamiResponse { - /** - * An individual login flow which can be used to sign into the remote network. - */ - export interface LoginFlow { - /** - * An internal ID that is passed to the /login/start call to start a login with - * this flow. - */ - id: string; - - /** - * A human-readable description of the login flow. - */ - description: string; - - /** - * A human-readable name for the login flow. - */ - name: string; - } - - /** - * The info of an individual login - */ - export interface Login { - /** - * The unique ID of a login. Defined by the network connector. - */ - id: string; - - /** - * A human-readable name for the login. Defined by the network connector. - */ - name: string; - - /** - * The profile info of the logged-in user on the remote network. - */ - profile: Login.Profile; - - /** - * The connection status of an individual login - */ - state: Login.State; - - /** - * The personal filtering space room ID for this login. - */ - space_room?: string; - } - - export namespace Login { - /** - * The profile info of the logged-in user on the remote network. - */ - export interface Profile { - /** - * The user's avatar - */ - avatar?: string; - - /** - * The user's email address - */ - email?: string; - - /** - * The user's displayname - */ - name?: string; - - /** - * The user's phone number - */ - phone?: string; - - /** - * The user's username - */ - username?: string; - } - - /** - * The connection status of an individual login - */ - export interface State { - /** - * The current state of this login. - */ - state_event: 'CONNECTING' | 'CONNECTED' | 'TRANSIENT_DISCONNECT' | 'BAD_CREDENTIALS' | 'UNKNOWN_ERROR'; - - /** - * The time when the state was last updated. - */ - timestamp: number; - - /** - * An error code defined by the network connector. - */ - error?: string; - - /** - * Additional arbitrary info provided by the network connector. - */ - info?: unknown; - - /** - * A human-readable error message defined by the network connector. - */ - message?: string; - - /** - * A reason code for non-error states that aren't exactly successes either. - */ - reason?: string; - } - } - - /** - * Info about the network that the bridge is bridging to. - */ - export interface Network { - /** - * An identifier uniquely identifying the bridge software. - */ - beeper_bridge_type: string; - - /** - * The displayname of the network. - */ - displayname: string; - - /** - * The icon of the network as a `mxc://` URI. - */ - network_icon: string; - - /** - * An identifier uniquely identifying the network. - */ - network_id: string; - - /** - * The URL to the website of the network. - */ - network_url: string; - } -} - -export interface AuthLogoutParams { - /** - * Bridge ID for the connected network account, for example discordgo or - * local-whatsapp. - */ - bridgeID: string; -} - -export interface AuthStartLoginParams { - /** - * Path param: Bridge ID for the connected network account, for example discordgo - * or local-whatsapp. - */ - bridgeID: string; - - /** - * Query param: An existing login ID to re-login as. If this is specified and the - * user logs into a different account, the provided ID will be logged out. - */ - login_id?: string; -} - -export interface AuthSubmitCookiesParams { - /** - * Path param: Bridge ID for the connected network account, for example discordgo - * or local-whatsapp. - */ - bridgeID: string; - - /** - * Path param: The ID of the login process, as returned in the `login_id` field of - * the start call. - */ - loginProcessID: string; - - /** - * Body param - */ - body: { [key: string]: string }; -} - -export interface AuthSubmitUserInputParams { - /** - * Path param: Bridge ID for the connected network account, for example discordgo - * or local-whatsapp. - */ - bridgeID: string; - - /** - * Path param: The ID of the login process, as returned in the `login_id` field of - * the start call. - */ - loginProcessID: string; - - /** - * Body param - */ - body: { [key: string]: string }; -} - -export interface AuthWaitForStepParams { - /** - * Bridge ID for the connected network account, for example discordgo or - * local-whatsapp. - */ - bridgeID: string; - - /** - * The ID of the login process, as returned in the `login_id` field of the start - * call. - */ - loginProcessID: string; -} - -export declare namespace Auth { - export { - type AuthListFlowsResponse as AuthListFlowsResponse, - type AuthListLoginsResponse as AuthListLoginsResponse, - type AuthLogoutResponse as AuthLogoutResponse, - type AuthStartLoginResponse as AuthStartLoginResponse, - type AuthSubmitCookiesResponse as AuthSubmitCookiesResponse, - type AuthSubmitUserInputResponse as AuthSubmitUserInputResponse, - type AuthWaitForStepResponse as AuthWaitForStepResponse, - type AuthWhoamiResponse as AuthWhoamiResponse, - type AuthLogoutParams as AuthLogoutParams, - type AuthStartLoginParams as AuthStartLoginParams, - type AuthSubmitCookiesParams as AuthSubmitCookiesParams, - type AuthSubmitUserInputParams as AuthSubmitUserInputParams, - type AuthWaitForStepParams as AuthWaitForStepParams, - }; -} diff --git a/src/resources/matrix/bridges/bridges.ts b/src/resources/matrix/bridges/bridges.ts deleted file mode 100644 index 5e70826d..00000000 --- a/src/resources/matrix/bridges/bridges.ts +++ /dev/null @@ -1,125 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as AuthAPI from './auth'; -import { - Auth, - AuthListFlowsResponse, - AuthListLoginsResponse, - AuthLogoutParams, - AuthLogoutResponse, - AuthStartLoginParams, - AuthStartLoginResponse, - AuthSubmitCookiesParams, - AuthSubmitCookiesResponse, - AuthSubmitUserInputParams, - AuthSubmitUserInputResponse, - AuthWaitForStepParams, - AuthWaitForStepResponse, - AuthWhoamiResponse, - BaseAuth, -} from './auth'; -import * as CapabilitiesAPI from './capabilities'; -import { BaseCapabilities, Capabilities, CapabilityRetrieveResponse } from './capabilities'; -import * as ContactsAPI from './contacts'; -import { BaseContacts, ContactListParams, ContactListResponse, Contacts } from './contacts'; -import * as RoomsAPI from './rooms'; -import { - BaseRooms, - RoomCreateDmParams, - RoomCreateDmResponse, - RoomCreateGroupParams, - RoomCreateGroupResponse, - Rooms, -} from './rooms'; -import * as UsersAPI from './users'; -import { - BaseUsers, - UserResolveParams, - UserResolveResponse, - UserSearchParams, - UserSearchResponse, - Users, -} from './users'; - -/** - * Matrix-compatible APIs for connected network bridges. - */ -export class BaseBridges extends APIResource { - static override readonly _key: readonly ['matrix', 'bridges'] = Object.freeze([ - 'matrix', - 'bridges', - ] as const); -} -/** - * Matrix-compatible APIs for connected network bridges. - */ -export class Bridges extends BaseBridges { - auth: AuthAPI.Auth = new AuthAPI.Auth(this._client); - contacts: ContactsAPI.Contacts = new ContactsAPI.Contacts(this._client); - users: UsersAPI.Users = new UsersAPI.Users(this._client); - rooms: RoomsAPI.Rooms = new RoomsAPI.Rooms(this._client); - capabilities: CapabilitiesAPI.Capabilities = new CapabilitiesAPI.Capabilities(this._client); -} - -Bridges.Auth = Auth; -Bridges.BaseAuth = BaseAuth; -Bridges.Contacts = Contacts; -Bridges.BaseContacts = BaseContacts; -Bridges.Users = Users; -Bridges.BaseUsers = BaseUsers; -Bridges.Rooms = Rooms; -Bridges.BaseRooms = BaseRooms; -Bridges.Capabilities = Capabilities; -Bridges.BaseCapabilities = BaseCapabilities; - -export declare namespace Bridges { - export { - Auth as Auth, - BaseAuth as BaseAuth, - type AuthListFlowsResponse as AuthListFlowsResponse, - type AuthListLoginsResponse as AuthListLoginsResponse, - type AuthLogoutResponse as AuthLogoutResponse, - type AuthStartLoginResponse as AuthStartLoginResponse, - type AuthSubmitCookiesResponse as AuthSubmitCookiesResponse, - type AuthSubmitUserInputResponse as AuthSubmitUserInputResponse, - type AuthWaitForStepResponse as AuthWaitForStepResponse, - type AuthWhoamiResponse as AuthWhoamiResponse, - type AuthLogoutParams as AuthLogoutParams, - type AuthStartLoginParams as AuthStartLoginParams, - type AuthSubmitCookiesParams as AuthSubmitCookiesParams, - type AuthSubmitUserInputParams as AuthSubmitUserInputParams, - type AuthWaitForStepParams as AuthWaitForStepParams, - }; - - export { - Contacts as Contacts, - BaseContacts as BaseContacts, - type ContactListResponse as ContactListResponse, - type ContactListParams as ContactListParams, - }; - - export { - Users as Users, - BaseUsers as BaseUsers, - type UserResolveResponse as UserResolveResponse, - type UserSearchResponse as UserSearchResponse, - type UserResolveParams as UserResolveParams, - type UserSearchParams as UserSearchParams, - }; - - export { - Rooms as Rooms, - BaseRooms as BaseRooms, - type RoomCreateDmResponse as RoomCreateDmResponse, - type RoomCreateGroupResponse as RoomCreateGroupResponse, - type RoomCreateDmParams as RoomCreateDmParams, - type RoomCreateGroupParams as RoomCreateGroupParams, - }; - - export { - Capabilities as Capabilities, - BaseCapabilities as BaseCapabilities, - type CapabilityRetrieveResponse as CapabilityRetrieveResponse, - }; -} diff --git a/src/resources/matrix/bridges/capabilities.ts b/src/resources/matrix/bridges/capabilities.ts deleted file mode 100644 index 40ac3b0a..00000000 --- a/src/resources/matrix/bridges/capabilities.ts +++ /dev/null @@ -1,45 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class BaseCapabilities extends APIResource { - static override readonly _key: readonly ['matrix', 'bridges', 'capabilities'] = Object.freeze([ - 'matrix', - 'bridges', - 'capabilities', - ] as const); - - /** - * Get bridge capabilities - * - * @example - * ```ts - * const capability = - * await client.matrix.bridges.capabilities.retrieve( - * 'bridgeID', - * ); - * ``` - */ - retrieve(bridgeID: string, options?: RequestOptions): APIPromise { - return this._client.get( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/capabilities`, - options, - ); - } -} -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class Capabilities extends BaseCapabilities {} - -export type CapabilityRetrieveResponse = { [key: string]: unknown }; - -export declare namespace Capabilities { - export { type CapabilityRetrieveResponse as CapabilityRetrieveResponse }; -} diff --git a/src/resources/matrix/bridges/contacts.ts b/src/resources/matrix/bridges/contacts.ts deleted file mode 100644 index 8df20884..00000000 --- a/src/resources/matrix/bridges/contacts.ts +++ /dev/null @@ -1,94 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class BaseContacts extends APIResource { - static override readonly _key: readonly ['matrix', 'bridges', 'contacts'] = Object.freeze([ - 'matrix', - 'bridges', - 'contacts', - ] as const); - - /** - * Get a list of contacts. - * - * @example - * ```ts - * const contacts = await client.matrix.bridges.contacts.list( - * 'bridgeID', - * ); - * ``` - */ - list( - bridgeID: string, - query: ContactListParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.get( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/contacts`, - { query, ...options }, - ); - } -} -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class Contacts extends BaseContacts {} - -export interface ContactListResponse { - contacts?: Array; -} - -export namespace ContactListResponse { - /** - * A successfully resolved identifier. - */ - export interface Contact { - /** - * The internal user ID of the resolved user. - */ - id: string; - - /** - * The avatar of the user on the remote network. - */ - avatar_url?: string; - - /** - * The Matrix room ID of the direct chat with the user. - */ - dm_room_mxid?: string; - - /** - * A list of identifiers for the user on the remote network. - */ - identifiers?: Array; - - /** - * The Matrix user ID of the ghost representing the user. - */ - mxid?: string; - - /** - * The name of the user on the remote network. - */ - name?: string; - } -} - -export interface ContactListParams { - /** - * An optional explicit login ID to do the action through. - */ - login_id?: string; -} - -export declare namespace Contacts { - export { type ContactListResponse as ContactListResponse, type ContactListParams as ContactListParams }; -} diff --git a/src/resources/matrix/bridges/index.ts b/src/resources/matrix/bridges/index.ts deleted file mode 100644 index f0230f7c..00000000 --- a/src/resources/matrix/bridges/index.ts +++ /dev/null @@ -1,38 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - Auth, - BaseAuth, - type AuthListFlowsResponse, - type AuthListLoginsResponse, - type AuthLogoutResponse, - type AuthStartLoginResponse, - type AuthSubmitCookiesResponse, - type AuthSubmitUserInputResponse, - type AuthWaitForStepResponse, - type AuthWhoamiResponse, - type AuthLogoutParams, - type AuthStartLoginParams, - type AuthSubmitCookiesParams, - type AuthSubmitUserInputParams, - type AuthWaitForStepParams, -} from './auth'; -export { Bridges, BaseBridges } from './bridges'; -export { Capabilities, BaseCapabilities, type CapabilityRetrieveResponse } from './capabilities'; -export { Contacts, BaseContacts, type ContactListResponse, type ContactListParams } from './contacts'; -export { - Rooms, - BaseRooms, - type RoomCreateDmResponse, - type RoomCreateGroupResponse, - type RoomCreateDmParams, - type RoomCreateGroupParams, -} from './rooms'; -export { - Users, - BaseUsers, - type UserResolveResponse, - type UserSearchResponse, - type UserResolveParams, - type UserSearchParams, -} from './users'; diff --git a/src/resources/matrix/bridges/rooms.ts b/src/resources/matrix/bridges/rooms.ts deleted file mode 100644 index d5275fa0..00000000 --- a/src/resources/matrix/bridges/rooms.ts +++ /dev/null @@ -1,231 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class BaseRooms extends APIResource { - static override readonly _key: readonly ['matrix', 'bridges', 'rooms'] = Object.freeze([ - 'matrix', - 'bridges', - 'rooms', - ] as const); - - /** - * Create a direct chat with a user on the remote network. - * - * @example - * ```ts - * const response = await client.matrix.bridges.rooms.createDm( - * 'identifier', - * { bridgeID: 'bridgeID' }, - * ); - * ``` - */ - createDm( - identifier: string, - params: RoomCreateDmParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID, login_id } = params; - return this._client.post( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/create_dm/${identifier}`, - { query: { login_id }, ...options }, - ); - } - - /** - * Create a group chat on the remote network. - * - * @example - * ```ts - * const response = - * await client.matrix.bridges.rooms.createGroup( - * 'groupType', - * { bridgeID: 'bridgeID' }, - * ); - * ``` - */ - createGroup( - groupType: string, - params: RoomCreateGroupParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID, login_id, ...body } = params; - return this._client.post( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/create_group/${groupType}`, - { query: { login_id }, body, ...options }, - ); - } -} -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class Rooms extends BaseRooms {} - -/** - * A successfully resolved identifier. - */ -export interface RoomCreateDmResponse { - /** - * The internal user ID of the resolved user. - */ - id: string; - - /** - * The avatar of the user on the remote network. - */ - avatar_url?: string; - - /** - * The Matrix room ID of the direct chat with the user. - */ - dm_room_mxid?: string; - - /** - * A list of identifiers for the user on the remote network. - */ - identifiers?: Array; - - /** - * The Matrix user ID of the ghost representing the user. - */ - mxid?: string; - - /** - * The name of the user on the remote network. - */ - name?: string; -} - -/** - * A successfully created group chat. - */ -export interface RoomCreateGroupResponse { - /** - * The internal chat ID of the created group. - */ - id: string; - - /** - * The Matrix room ID of the portal. - */ - mxid: string; -} - -export interface RoomCreateDmParams { - /** - * Path param: Bridge ID for the connected network account, for example discordgo - * or local-whatsapp. - */ - bridgeID: string; - - /** - * Query param: An optional explicit login ID to do the action through. - */ - login_id?: string; -} - -export interface RoomCreateGroupParams { - /** - * Path param: Bridge ID for the connected network account, for example discordgo - * or local-whatsapp. - */ - bridgeID: string; - - /** - * Query param: An optional explicit login ID to do the action through. - */ - login_id?: string; - - /** - * Body param: The `m.room.avatar` event content for the room. - */ - avatar?: RoomCreateGroupParams.Avatar; - - /** - * Body param: The `com.beeper.disappearing_timer` event content for the room. - */ - disappear?: RoomCreateGroupParams.Disappear; - - /** - * Body param: The `m.room.name` event content for the room. - */ - name?: RoomCreateGroupParams.Name; - - /** - * Body param - */ - parent?: unknown; - - /** - * Body param: The users to add to the group initially. - */ - participants?: Array; - - /** - * Body param: An existing Matrix room ID to bridge to. The other parameters must - * be already in sync with the room state when using this parameter. - */ - room_id?: string; - - /** - * Body param: The `m.room.topic` event content for the room. - */ - topic?: RoomCreateGroupParams.Topic; - - /** - * Body param: The type of group to create. - */ - type?: string; - - /** - * Body param: The public username for the created group. - */ - username?: string; -} - -export namespace RoomCreateGroupParams { - /** - * The `m.room.avatar` event content for the room. - */ - export interface Avatar { - url?: string; - } - - /** - * The `com.beeper.disappearing_timer` event content for the room. - */ - export interface Disappear { - timer?: number; - - type?: string; - } - - /** - * The `m.room.name` event content for the room. - */ - export interface Name { - name?: string; - } - - /** - * The `m.room.topic` event content for the room. - */ - export interface Topic { - topic?: string; - } -} - -export declare namespace Rooms { - export { - type RoomCreateDmResponse as RoomCreateDmResponse, - type RoomCreateGroupResponse as RoomCreateGroupResponse, - type RoomCreateDmParams as RoomCreateDmParams, - type RoomCreateGroupParams as RoomCreateGroupParams, - }; -} diff --git a/src/resources/matrix/bridges/users.ts b/src/resources/matrix/bridges/users.ts deleted file mode 100644 index 473c9235..00000000 --- a/src/resources/matrix/bridges/users.ts +++ /dev/null @@ -1,176 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class BaseUsers extends APIResource { - static override readonly _key: readonly ['matrix', 'bridges', 'users'] = Object.freeze([ - 'matrix', - 'bridges', - 'users', - ] as const); - - /** - * Resolve an identifier to a user on the remote network. - * - * @example - * ```ts - * const response = await client.matrix.bridges.users.resolve( - * 'identifier', - * { bridgeID: 'bridgeID' }, - * ); - * ``` - */ - resolve( - identifier: string, - params: UserResolveParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID, ...query } = params; - return this._client.get( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/resolve_identifier/${identifier}`, - { query, ...options }, - ); - } - - /** - * Search for users on the remote network - * - * @example - * ```ts - * const response = await client.matrix.bridges.users.search( - * 'bridgeID', - * ); - * ``` - */ - search( - bridgeID: string, - params: UserSearchParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - const { login_id, ...body } = params ?? {}; - return this._client.post( - path`/_matrix/client/unstable/com.beeper.bridge/${bridgeID}/_matrix/provision/v3/search_users`, - { query: { login_id }, body, ...options }, - ); - } -} -/** - * Matrix-compatible APIs for accounts and connected network bridges. - */ -export class Users extends BaseUsers {} - -/** - * A successfully resolved identifier. - */ -export interface UserResolveResponse { - /** - * The internal user ID of the resolved user. - */ - id: string; - - /** - * The avatar of the user on the remote network. - */ - avatar_url?: string; - - /** - * The Matrix room ID of the direct chat with the user. - */ - dm_room_mxid?: string; - - /** - * A list of identifiers for the user on the remote network. - */ - identifiers?: Array; - - /** - * The Matrix user ID of the ghost representing the user. - */ - mxid?: string; - - /** - * The name of the user on the remote network. - */ - name?: string; -} - -export interface UserSearchResponse { - results?: Array; -} - -export namespace UserSearchResponse { - /** - * A successfully resolved identifier. - */ - export interface Result { - /** - * The internal user ID of the resolved user. - */ - id: string; - - /** - * The avatar of the user on the remote network. - */ - avatar_url?: string; - - /** - * The Matrix room ID of the direct chat with the user. - */ - dm_room_mxid?: string; - - /** - * A list of identifiers for the user on the remote network. - */ - identifiers?: Array; - - /** - * The Matrix user ID of the ghost representing the user. - */ - mxid?: string; - - /** - * The name of the user on the remote network. - */ - name?: string; - } -} - -export interface UserResolveParams { - /** - * Path param: Bridge ID for the connected network account, for example discordgo - * or local-whatsapp. - */ - bridgeID: string; - - /** - * Query param: An optional explicit login ID to do the action through. - */ - login_id?: string; -} - -export interface UserSearchParams { - /** - * Query param: An optional explicit login ID to do the action through. - */ - login_id?: string; - - /** - * Body param: The search query to send to the remote network - */ - query?: string; -} - -export declare namespace Users { - export { - type UserResolveResponse as UserResolveResponse, - type UserSearchResponse as UserSearchResponse, - type UserResolveParams as UserResolveParams, - type UserSearchParams as UserSearchParams, - }; -} diff --git a/src/resources/matrix/index.ts b/src/resources/matrix/index.ts deleted file mode 100644 index 3da24c40..00000000 --- a/src/resources/matrix/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { Bridges, BaseBridges } from './bridges/index'; -export { Matrix, BaseMatrix } from './matrix'; -export { - Rooms, - BaseRooms, - type RoomCreateResponse, - type RoomJoinResponse, - type RoomLeaveResponse, - type RoomCreateParams, - type RoomJoinParams, - type RoomLeaveParams, -} from './rooms/index'; -export { Users, BaseUsers, type UserRetrieveProfileResponse } from './users/index'; diff --git a/src/resources/matrix/matrix.ts b/src/resources/matrix/matrix.ts deleted file mode 100644 index 33b6e940..00000000 --- a/src/resources/matrix/matrix.ts +++ /dev/null @@ -1,61 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../core/resource'; -import * as BridgesAPI from './bridges/bridges'; -import { BaseBridges, Bridges } from './bridges/bridges'; -import * as RoomsAPI from './rooms/rooms'; -import { - BaseRooms, - RoomCreateParams, - RoomCreateResponse, - RoomJoinParams, - RoomJoinResponse, - RoomLeaveParams, - RoomLeaveResponse, - Rooms, -} from './rooms/rooms'; -import * as UsersAPI from './users/users'; -import { BaseUsers, UserRetrieveProfileResponse, Users } from './users/users'; - -/** - * Matrix-compatible APIs for accounts, rooms, and connected network bridges. - */ -export class BaseMatrix extends APIResource { - static override readonly _key: readonly ['matrix'] = Object.freeze(['matrix'] as const); -} -/** - * Matrix-compatible APIs for accounts, rooms, and connected network bridges. - */ -export class Matrix extends BaseMatrix { - users: UsersAPI.Users = new UsersAPI.Users(this._client); - rooms: RoomsAPI.Rooms = new RoomsAPI.Rooms(this._client); - bridges: BridgesAPI.Bridges = new BridgesAPI.Bridges(this._client); -} - -Matrix.Users = Users; -Matrix.BaseUsers = BaseUsers; -Matrix.Rooms = Rooms; -Matrix.BaseRooms = BaseRooms; -Matrix.Bridges = Bridges; -Matrix.BaseBridges = BaseBridges; - -export declare namespace Matrix { - export { - Users as Users, - BaseUsers as BaseUsers, - type UserRetrieveProfileResponse as UserRetrieveProfileResponse, - }; - - export { - Rooms as Rooms, - BaseRooms as BaseRooms, - type RoomCreateResponse as RoomCreateResponse, - type RoomJoinResponse as RoomJoinResponse, - type RoomLeaveResponse as RoomLeaveResponse, - type RoomCreateParams as RoomCreateParams, - type RoomJoinParams as RoomJoinParams, - type RoomLeaveParams as RoomLeaveParams, - }; - - export { Bridges as Bridges, BaseBridges as BaseBridges }; -} diff --git a/src/resources/matrix/rooms.ts b/src/resources/matrix/rooms.ts deleted file mode 100644 index 22113d24..00000000 --- a/src/resources/matrix/rooms.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './rooms/index'; diff --git a/src/resources/matrix/rooms/account-data.ts b/src/resources/matrix/rooms/account-data.ts deleted file mode 100644 index e2fcd393..00000000 --- a/src/resources/matrix/rooms/account-data.ts +++ /dev/null @@ -1,113 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class BaseAccountData extends APIResource { - static override readonly _key: readonly ['matrix', 'rooms', 'accountData'] = Object.freeze([ - 'matrix', - 'rooms', - 'accountData', - ] as const); - - /** - * Get some account data for the client on a given room. This config is only - * visible to the user that set the account data. - * - * @example - * ```ts - * const accountData = - * await client.matrix.rooms.accountData.retrieve( - * 'org.example.custom.room.config', - * { - * userId: '@alice:example.com', - * roomId: '!726s6s6q:example.com', - * }, - * ); - * ``` - */ - retrieve(type: string, params: AccountDataRetrieveParams, options?: RequestOptions): APIPromise { - const { userId, roomId } = params; - return this._client.get( - path`/_matrix/client/v3/user/${userId}/rooms/${roomId}/account_data/${type}`, - options, - ); - } - - /** - * Set some account data for the client on a given room. This config is only - * visible to the user that set the account data. The config will be delivered to - * clients in the per-room entries via - * [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync). - * - * @example - * ```ts - * const accountData = - * await client.matrix.rooms.accountData.update( - * 'org.example.custom.room.config', - * { - * userId: '@alice:example.com', - * roomId: '!726s6s6q:example.com', - * body: { - * custom_account_data_key: - * 'custom_account_data_value', - * }, - * }, - * ); - * ``` - */ - update(type: string, params: AccountDataUpdateParams, options?: RequestOptions): APIPromise { - const { userId, roomId, body } = params; - return this._client.put(path`/_matrix/client/v3/user/${userId}/rooms/${roomId}/account_data/${type}`, { - body: body, - ...options, - }); - } -} -export class AccountData extends BaseAccountData {} - -export type AccountDataRetrieveResponse = unknown; - -export type AccountDataUpdateResponse = unknown; - -export interface AccountDataRetrieveParams { - /** - * The ID of the user to get account data for. The access token must be authorized - * to make requests for this user ID. - */ - userId: string; - - /** - * The ID of the room to get account data for. - */ - roomId: string; -} - -export interface AccountDataUpdateParams { - /** - * Path param: The ID of the user to set account data for. The access token must be - * authorized to make requests for this user ID. - */ - userId: string; - - /** - * Path param: The ID of the room to set account data on. - */ - roomId: string; - - /** - * Body param - */ - body: unknown; -} - -export declare namespace AccountData { - export { - type AccountDataRetrieveResponse as AccountDataRetrieveResponse, - type AccountDataUpdateResponse as AccountDataUpdateResponse, - type AccountDataRetrieveParams as AccountDataRetrieveParams, - type AccountDataUpdateParams as AccountDataUpdateParams, - }; -} diff --git a/src/resources/matrix/rooms/events.ts b/src/resources/matrix/rooms/events.ts deleted file mode 100644 index b8fe4e22..00000000 --- a/src/resources/matrix/rooms/events.ts +++ /dev/null @@ -1,148 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class BaseEvents extends APIResource { - static override readonly _key: readonly ['matrix', 'rooms', 'events'] = Object.freeze([ - 'matrix', - 'rooms', - 'events', - ] as const); - - /** - * Get a single event based on `roomId/eventId`. You must have permission to - * retrieve this event e.g. by being a member in the room for this event. - * - * @example - * ```ts - * const event = await client.matrix.rooms.events.retrieve( - * '$asfDuShaf7Gafaw:matrix.org', - * { roomId: '!636q39766251:matrix.org' }, - * ); - * ``` - */ - retrieve( - eventID: string, - params: EventRetrieveParams, - options?: RequestOptions, - ): APIPromise { - const { roomId } = params; - return this._client.get(path`/_matrix/client/v3/rooms/${roomId}/event/${eventID}`, options); - } -} -export class Events extends BaseEvents {} - -/** - * The format used for events when they are returned from a homeserver to a client - * via the Client-Server API, or sent to an Application Service via the Application - * Services API. - */ -export interface EventRetrieveResponse { - /** - * The body of this event, as created by the client which sent it. - */ - content: unknown; - - /** - * The globally unique identifier for this event. - */ - event_id: string; - - /** - * Timestamp (in milliseconds since the unix epoch) on originating homeserver when - * this event was sent. - */ - origin_server_ts: number; - - /** - * The ID of the room associated with this event. - */ - room_id: string; - - /** - * Contains the fully-qualified ID of the user who sent this event. - */ - sender: string; - - /** - * The type of the event. - */ - type: string; - - /** - * Present if, and only if, this event is a _state_ event. The key making this - * piece of state unique in the room. Note that it is often an empty string. - * - * State keys starting with an `@` are reserved for referencing user IDs, such as - * room members. With the exception of a few events, state events set with a given - * user's ID as the state key MUST only be set by that user. - */ - state_key?: string; - - unsigned?: EventRetrieveResponse.Unsigned; -} - -export namespace EventRetrieveResponse { - export interface Unsigned { - /** - * The time in milliseconds that has elapsed since the event was sent. This field - * is generated by the local homeserver, and may be incorrect if the local time on - * at least one of the two servers is out of sync, which can cause the age to - * either be negative or greater than it actually is. - */ - age?: number; - - /** - * The room membership of the user making the request, at the time of the event. - * - * This property is the value of the `membership` property of the requesting user's - * [`m.room.member`](https://spec.matrix.org/v1.18/client-server-api#mroommember) - * state at the point of the event, including any changes caused by the event. If - * the user had yet to join the room at the time of the event (i.e, they have no - * `m.room.member` state), this property is set to `leave`. - * - * Homeservers SHOULD populate this property wherever practical, but they MAY omit - * it if necessary (for example, if calculating the value is expensive, servers - * might choose to only implement it in encrypted rooms). The property is _not_ - * normally populated in events pushed to application services via the application - * service transaction API (where there is no clear definition of "requesting - * user"). - */ - membership?: string; - - /** - * The previous `content` for this event. This field is generated by the local - * homeserver, and is only returned if the event is a state event, and the client - * has permission to see the previous content. - */ - prev_content?: unknown; - - redacted_because?: unknown; - - /** - * The client-supplied - * [transaction ID](https://spec.matrix.org/v1.18/client-server-api/#transaction-identifiers), - * for example, provided via - * `PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}`, if the client - * being given the event is the same one which sent it. - */ - transaction_id?: string; - } -} - -export interface EventRetrieveParams { - /** - * The ID of the room the event is in. - */ - roomId: string; -} - -export declare namespace Events { - export { - type EventRetrieveResponse as EventRetrieveResponse, - type EventRetrieveParams as EventRetrieveParams, - }; -} diff --git a/src/resources/matrix/rooms/index.ts b/src/resources/matrix/rooms/index.ts deleted file mode 100644 index 7c206b25..00000000 --- a/src/resources/matrix/rooms/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - AccountData, - BaseAccountData, - type AccountDataRetrieveResponse, - type AccountDataUpdateResponse, - type AccountDataRetrieveParams, - type AccountDataUpdateParams, -} from './account-data'; -export { Events, BaseEvents, type EventRetrieveResponse, type EventRetrieveParams } from './events'; -export { - Rooms, - BaseRooms, - type RoomCreateResponse, - type RoomJoinResponse, - type RoomLeaveResponse, - type RoomCreateParams, - type RoomJoinParams, - type RoomLeaveParams, -} from './rooms'; -export { - State, - BaseState, - type StateRetrieveResponse, - type StateListResponse, - type StateRetrieveParams, -} from './state'; diff --git a/src/resources/matrix/rooms/rooms.ts b/src/resources/matrix/rooms/rooms.ts deleted file mode 100644 index 9c4456ca..00000000 --- a/src/resources/matrix/rooms/rooms.ts +++ /dev/null @@ -1,435 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as AccountDataAPI from './account-data'; -import { - AccountData, - AccountDataRetrieveParams, - AccountDataRetrieveResponse, - AccountDataUpdateParams, - AccountDataUpdateResponse, - BaseAccountData, -} from './account-data'; -import * as EventsAPI from './events'; -import { BaseEvents, EventRetrieveParams, EventRetrieveResponse, Events } from './events'; -import * as StateAPI from './state'; -import { BaseState, State, StateListResponse, StateRetrieveParams, StateRetrieveResponse } from './state'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class BaseRooms extends APIResource { - static override readonly _key: readonly ['matrix', 'rooms'] = Object.freeze(['matrix', 'rooms'] as const); - - /** - * Create a new room with various configuration options. - * - * The server MUST apply the normal state resolution rules when creating the new - * room, including checking power levels for each event. It MUST apply the events - * implied by the request in the following order: - * - * 1. The `m.room.create` event itself. Must be the first event in the room. - * - * 2. An `m.room.member` event for the creator to join the room. This is needed so - * the remaining events can be sent. - * - * 3. A default `m.room.power_levels` event. Overridden by the - * `power_level_content_override` parameter. - * - * In [room versions](https://spec.matrix.org/v1.18/rooms) 1 through 11, the - * room creator (and not other members) will be given permission to send state - * events. - * - * In room versions 12 and later, the room creator is given infinite power level - * and cannot be specified in the `users` field of `m.room.power_levels`, so is - * not listed explicitly. - * - * **Note**: For `trusted_private_chat`, the users specified in the `invite` - * parameter SHOULD also be appended to `additional_creators` by the server, per - * the `creation_content` parameter. - * - * If the room's version is 12 or higher, the power level for sending - * `m.room.tombstone` events MUST explicitly be higher than `state_default`. For - * example, set to 150 instead of 100. - * - * 4. An `m.room.canonical_alias` event if `room_alias_name` is given. - * - * 5. Events set by the `preset`. Currently these are the `m.room.join_rules`, - * `m.room.history_visibility`, and `m.room.guest_access` state events. - * - * 6. Events listed in `initial_state`, in the order that they are listed. - * - * 7. Events implied by `name` and `topic` (`m.room.name` and `m.room.topic` state - * events). - * - * 8. Invite events implied by `invite` and `invite_3pid` (`m.room.member` with - * `membership: invite` and `m.room.third_party_invite`). - * - * The available presets do the following with respect to room state: - * - * | Preset | `join_rules` | `history_visibility` | `guest_access` | Other | - * | ---------------------- | ------------ | -------------------- | -------------- | ---------------------------------------------------------------- | - * | `private_chat` | `invite` | `shared` | `can_join` | | - * | `trusted_private_chat` | `invite` | `shared` | `can_join` | All invitees are given the same power level as the room creator. | - * | `public_chat` | `public` | `shared` | `forbidden` | | - * - * The server will create a `m.room.create` event in the room with the requesting - * user as the creator, alongside other keys provided in the `creation_content` or - * implied by behaviour of `creation_content`. - * - * @example - * ```ts - * const room = await client.matrix.rooms.create(); - * ``` - */ - create(body: RoomCreateParams, options?: RequestOptions): APIPromise { - return this._client.post('/_matrix/client/v3/createRoom', { body, ...options }); - } - - /** - * _Note that this API takes either a room ID or alias, unlike_ - * `/rooms/{roomId}/join`. - * - * This API starts a user's participation in a particular room, if that user is - * allowed to participate in that room. After this call, the client is allowed to - * see all current state events in the room, and all subsequent events associated - * with the room until the user leaves the room. - * - * After a user has joined a room, the room will appear as an entry in the response - * of the - * [`/initialSync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3initialsync) - * and - * [`/sync`](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync) - * APIs. - * - * @example - * ```ts - * const response = await client.matrix.rooms.join( - * '!monkeys:matrix.org', - * ); - * ``` - */ - join( - roomIDOrAlias: string, - params: RoomJoinParams, - options?: RequestOptions, - ): APIPromise { - const { via, ...body } = params; - return this._client.post(path`/_matrix/client/v3/join/${roomIDOrAlias}`, { - query: { via }, - body, - ...options, - }); - } - - /** - * This API stops a user participating in a particular room. - * - * If the user was already in the room, they will no longer be able to see new - * events in the room. If the room requires an invite to join, they will need to be - * re-invited before they can re-join. - * - * If the user was invited to the room, but had not joined, this call serves to - * reject the invite. - * - * Servers MAY additionally forget the room when this endpoint is called – just as - * if the user had also invoked - * [`/forget`](https://spec.matrix.org/v1.18/client-server-api/#post_matrixclientv3roomsroomidforget). - * Servers that do this, MUST inform clients about this behavior using the - * [`m.forget_forced_upon_leave`](https://spec.matrix.org/v1.18/client-server-api/#mforget_forced_upon_leave-capability) - * capability. - * - * If the server doesn't automatically forget the room, the user will still be - * allowed to retrieve history from the room which they were previously allowed to - * see. - * - * @example - * ```ts - * const response = await client.matrix.rooms.leave( - * '!nkl290a:matrix.org', - * ); - * ``` - */ - leave(roomID: string, body: RoomLeaveParams, options?: RequestOptions): APIPromise { - return this._client.post(path`/_matrix/client/v3/rooms/${roomID}/leave`, { body, ...options }); - } -} -export class Rooms extends BaseRooms { - accountData: AccountDataAPI.AccountData = new AccountDataAPI.AccountData(this._client); - state: StateAPI.State = new StateAPI.State(this._client); - events: EventsAPI.Events = new EventsAPI.Events(this._client); -} - -/** - * Information about the newly created room. - */ -export interface RoomCreateResponse { - /** - * The created room's ID. - */ - room_id: string; -} - -export interface RoomJoinResponse { - /** - * The joined room ID. - */ - room_id: string; -} - -export type RoomLeaveResponse = unknown; - -export interface RoomCreateParams { - /** - * Extra keys, such as `m.federate`, to be added to the content of the - * [`m.room.create`](https://spec.matrix.org/v1.18/client-server-api/#mroomcreate) - * event. - * - * The server will overwrite the following keys: `creator`, `room_version`. Future - * versions of the specification may allow the server to overwrite other keys. - * - * When using the `trusted_private_chat` preset, the server SHOULD combine - * `additional_creators` specified here and the `invite` array into the eventual - * `m.room.create` event's `additional_creators`, deduplicating between the two - * parameters. - */ - creation_content?: unknown; - - /** - * A list of state events to set in the new room. This allows the user to override - * the default state events set in the new room. The expected format of the state - * events are an object with type, state_key and content keys set. - * - * Takes precedence over events set by `preset`, but gets overridden by `name` and - * `topic` keys. - */ - initial_state?: Array; - - /** - * A list of user IDs to invite to the room. This will tell the server to invite - * everyone in the list to the newly created room. - */ - invite?: Array; - - /** - * A list of objects representing third-party IDs to invite into the room. - */ - invite_3pid?: Array; - - /** - * This flag makes the server set the `is_direct` flag on the `m.room.member` - * events sent to the users in `invite` and `invite_3pid`. See - * [Direct Messaging](https://spec.matrix.org/v1.18/client-server-api/#direct-messaging) - * for more information. - */ - is_direct?: boolean; - - /** - * If this is included, an - * [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname) - * event will be sent into the room to indicate the name for the room. This - * overwrites any - * [`m.room.name`](https://spec.matrix.org/v1.18/client-server-api/#mroomname) - * event in `initial_state`. - */ - name?: string; - - /** - * The power level content to override in the default power level event. This - * object is applied on top of the generated - * [`m.room.power_levels`](https://spec.matrix.org/v1.18/client-server-api/#mroompower_levels) - * event content prior to it being sent to the room. Defaults to overriding - * nothing. - */ - power_level_content_override?: unknown; - - /** - * Convenience parameter for setting various default state events based on a - * preset. - * - * If unspecified, the server should use the `visibility` to determine which preset - * to use. A visibility of `public` equates to a preset of `public_chat` and - * `private` visibility equates to a preset of `private_chat`. - */ - preset?: 'private_chat' | 'public_chat' | 'trusted_private_chat'; - - /** - * The desired room alias **local part**. If this is included, a room alias will be - * created and mapped to the newly created room. The alias will belong on the - * _same_ homeserver which created the room. For example, if this was set to "foo" - * and sent to the homeserver "example.com" the complete room alias would be - * `#foo:example.com`. - * - * The complete room alias will become the canonical alias for the room and an - * `m.room.canonical_alias` event will be sent into the room. - */ - room_alias_name?: string; - - /** - * The room version to set for the room. If not provided, the homeserver is to use - * its configured default. If provided, the homeserver will return a 400 error with - * the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not support the room - * version. - */ - room_version?: string; - - /** - * If this is included, an - * [`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic) - * event with a `text/plain` mimetype will be sent into the room to indicate the - * topic for the room. This overwrites any - * [`m.room.topic`](https://spec.matrix.org/v1.18/client-server-api/#mroomtopic) - * event in `initial_state`. - */ - topic?: string; - - /** - * The room's visibility in the server's - * [published room directory](https://spec.matrix.org/v1.18/client-server-api#published-room-directory). - * Defaults to `private`. - */ - visibility?: 'public' | 'private'; -} - -export namespace RoomCreateParams { - export interface InitialState { - /** - * The content of the event. - */ - content: unknown; - - /** - * The type of event to send. - */ - type: string; - - /** - * The state_key of the state event. Defaults to an empty string. - */ - state_key?: string; - } - - export interface Invite3pid { - /** - * The invitee's third-party identifier. - */ - address: string; - - /** - * An access token previously registered with the identity server. Servers can - * treat this as optional to distinguish between r0.5-compatible clients and this - * specification version. - */ - id_access_token: string; - - /** - * The hostname+port of the identity server which should be used for third-party - * identifier lookups. - */ - id_server: string; - - /** - * The kind of address being passed in the address field, for example `email` (see - * [the list of recognised values](https://spec.matrix.org/v1.18/appendices/#3pid-types)). - */ - medium: string; - } -} - -export interface RoomJoinParams { - /** - * Query param: The servers to attempt to join the room through. One of the servers - * must be participating in the room. - */ - via?: Array; - - /** - * Body param: Optional reason to be included as the `reason` on the subsequent - * membership event. - */ - reason?: string; - - /** - * Body param: A signature of an `m.third_party_invite` token to prove that this - * user owns a third-party identity which has been invited to the room. - */ - third_party_signed?: RoomJoinParams.ThirdPartySigned; -} - -export namespace RoomJoinParams { - /** - * A signature of an `m.third_party_invite` token to prove that this user owns a - * third-party identity which has been invited to the room. - */ - export interface ThirdPartySigned { - /** - * The state key of the m.third_party_invite event. - */ - token: string; - - /** - * The Matrix ID of the invitee. - */ - mxid: string; - - /** - * The Matrix ID of the user who issued the invite. - */ - sender: string; - - /** - * A signatures object containing a signature of the entire signed object. - */ - signatures: { [key: string]: { [key: string]: string } }; - } -} - -export interface RoomLeaveParams { - /** - * Optional reason to be included as the `reason` on the subsequent membership - * event. - */ - reason?: string; -} - -Rooms.AccountData = AccountData; -Rooms.BaseAccountData = BaseAccountData; -Rooms.State = State; -Rooms.BaseState = BaseState; -Rooms.Events = Events; -Rooms.BaseEvents = BaseEvents; - -export declare namespace Rooms { - export { - type RoomCreateResponse as RoomCreateResponse, - type RoomJoinResponse as RoomJoinResponse, - type RoomLeaveResponse as RoomLeaveResponse, - type RoomCreateParams as RoomCreateParams, - type RoomJoinParams as RoomJoinParams, - type RoomLeaveParams as RoomLeaveParams, - }; - - export { - AccountData as AccountData, - BaseAccountData as BaseAccountData, - type AccountDataRetrieveResponse as AccountDataRetrieveResponse, - type AccountDataUpdateResponse as AccountDataUpdateResponse, - type AccountDataRetrieveParams as AccountDataRetrieveParams, - type AccountDataUpdateParams as AccountDataUpdateParams, - }; - - export { - State as State, - BaseState as BaseState, - type StateRetrieveResponse as StateRetrieveResponse, - type StateListResponse as StateListResponse, - type StateRetrieveParams as StateRetrieveParams, - }; - - export { - Events as Events, - BaseEvents as BaseEvents, - type EventRetrieveResponse as EventRetrieveResponse, - type EventRetrieveParams as EventRetrieveParams, - }; -} diff --git a/src/resources/matrix/rooms/state.ts b/src/resources/matrix/rooms/state.ts deleted file mode 100644 index 870adf6d..00000000 --- a/src/resources/matrix/rooms/state.ts +++ /dev/null @@ -1,194 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class BaseState extends APIResource { - static override readonly _key: readonly ['matrix', 'rooms', 'state'] = Object.freeze([ - 'matrix', - 'rooms', - 'state', - ] as const); - - /** - * Looks up the contents of a state event in a room. If the user is joined to the - * room then the state is taken from the current state of the room. If the user has - * left the room then the state is taken from the state of the room when they left. - * - * @example - * ```ts - * const state = await client.matrix.rooms.state.retrieve( - * 'state_key', - * { - * roomId: '!636q39766251:example.com', - * eventType: 'm.room.name', - * }, - * ); - * ``` - */ - retrieve( - stateKey: string, - params: StateRetrieveParams, - options?: RequestOptions, - ): APIPromise { - const { roomId, eventType, ...query } = params; - return this._client.get(path`/_matrix/client/v3/rooms/${roomId}/state/${eventType}/${stateKey}`, { - query, - ...options, - }); - } - - /** - * Get the state events for the current state of a room. - * - * @example - * ```ts - * const states = await client.matrix.rooms.state.list( - * '!636q39766251:example.com', - * ); - * ``` - */ - list(roomID: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/_matrix/client/v3/rooms/${roomID}/state`, options); - } -} -export class State extends BaseState {} - -export type StateRetrieveResponse = { [key: string]: unknown }; - -/** - * If the user is a member of the room this will be the current state of the room - * as a list of events. If the user has left the room then this will be the state - * of the room when they left as a list of events. - */ -export type StateListResponse = Array; - -export namespace StateListResponse { - /** - * The format used for events when they are returned from a homeserver to a client - * via the Client-Server API, or sent to an Application Service via the Application - * Services API. - */ - export interface StateListResponseItem { - /** - * The body of this event, as created by the client which sent it. - */ - content: unknown; - - /** - * The globally unique identifier for this event. - */ - event_id: string; - - /** - * Timestamp (in milliseconds since the unix epoch) on originating homeserver when - * this event was sent. - */ - origin_server_ts: number; - - /** - * The ID of the room associated with this event. - */ - room_id: string; - - /** - * Contains the fully-qualified ID of the user who sent this event. - */ - sender: string; - - /** - * The type of the event. - */ - type: string; - - /** - * Present if, and only if, this event is a _state_ event. The key making this - * piece of state unique in the room. Note that it is often an empty string. - * - * State keys starting with an `@` are reserved for referencing user IDs, such as - * room members. With the exception of a few events, state events set with a given - * user's ID as the state key MUST only be set by that user. - */ - state_key?: string; - - unsigned?: StateListResponseItem.Unsigned; - } - - export namespace StateListResponseItem { - export interface Unsigned { - /** - * The time in milliseconds that has elapsed since the event was sent. This field - * is generated by the local homeserver, and may be incorrect if the local time on - * at least one of the two servers is out of sync, which can cause the age to - * either be negative or greater than it actually is. - */ - age?: number; - - /** - * The room membership of the user making the request, at the time of the event. - * - * This property is the value of the `membership` property of the requesting user's - * [`m.room.member`](https://spec.matrix.org/v1.18/client-server-api#mroommember) - * state at the point of the event, including any changes caused by the event. If - * the user had yet to join the room at the time of the event (i.e, they have no - * `m.room.member` state), this property is set to `leave`. - * - * Homeservers SHOULD populate this property wherever practical, but they MAY omit - * it if necessary (for example, if calculating the value is expensive, servers - * might choose to only implement it in encrypted rooms). The property is _not_ - * normally populated in events pushed to application services via the application - * service transaction API (where there is no clear definition of "requesting - * user"). - */ - membership?: string; - - /** - * The previous `content` for this event. This field is generated by the local - * homeserver, and is only returned if the event is a state event, and the client - * has permission to see the previous content. - */ - prev_content?: unknown; - - redacted_because?: unknown; - - /** - * The client-supplied - * [transaction ID](https://spec.matrix.org/v1.18/client-server-api/#transaction-identifiers), - * for example, provided via - * `PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}`, if the client - * being given the event is the same one which sent it. - */ - transaction_id?: string; - } - } -} - -export interface StateRetrieveParams { - /** - * Path param: The room to look up the state in. - */ - roomId: string; - - /** - * Path param: The type of state to look up. - */ - eventType: string; - - /** - * Query param: The format to use for the returned data. `content` (the default) - * will return only the content of the state event. `event` will return the entire - * event in the usual format suitable for clients, including fields like event ID, - * sender and timestamp. - */ - format?: 'content' | 'event'; -} - -export declare namespace State { - export { - type StateRetrieveResponse as StateRetrieveResponse, - type StateListResponse as StateListResponse, - type StateRetrieveParams as StateRetrieveParams, - }; -} diff --git a/src/resources/matrix/users.ts b/src/resources/matrix/users.ts deleted file mode 100644 index db908c70..00000000 --- a/src/resources/matrix/users.ts +++ /dev/null @@ -1,3 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export * from './users/index'; diff --git a/src/resources/matrix/users/account-data.ts b/src/resources/matrix/users/account-data.ts deleted file mode 100644 index 4a009311..00000000 --- a/src/resources/matrix/users/account-data.ts +++ /dev/null @@ -1,95 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class BaseAccountData extends APIResource { - static override readonly _key: readonly ['matrix', 'users', 'accountData'] = Object.freeze([ - 'matrix', - 'users', - 'accountData', - ] as const); - - /** - * Get some account data for the client. This config is only visible to the user - * that set the account data. - * - * @example - * ```ts - * const accountData = - * await client.matrix.users.accountData.retrieve( - * 'org.example.custom.config', - * { userId: '@alice:example.com' }, - * ); - * ``` - */ - retrieve(type: string, params: AccountDataRetrieveParams, options?: RequestOptions): APIPromise { - const { userId } = params; - return this._client.get(path`/_matrix/client/v3/user/${userId}/account_data/${type}`, options); - } - - /** - * Set some account data for the client. This config is only visible to the user - * that set the account data. The config will be available to clients through the - * top-level `account_data` field in the homeserver response to - * [/sync](https://spec.matrix.org/v1.18/client-server-api/#get_matrixclientv3sync). - * - * @example - * ```ts - * const accountData = - * await client.matrix.users.accountData.update( - * 'org.example.custom.config', - * { - * userId: '@alice:example.com', - * body: { - * custom_account_data_key: 'custom_config_value', - * }, - * }, - * ); - * ``` - */ - update(type: string, params: AccountDataUpdateParams, options?: RequestOptions): APIPromise { - const { userId, body } = params; - return this._client.put(path`/_matrix/client/v3/user/${userId}/account_data/${type}`, { - body: body, - ...options, - }); - } -} -export class AccountData extends BaseAccountData {} - -export type AccountDataRetrieveResponse = unknown; - -export type AccountDataUpdateResponse = unknown; - -export interface AccountDataRetrieveParams { - /** - * The ID of the user to get account data for. The access token must be authorized - * to make requests for this user ID. - */ - userId: string; -} - -export interface AccountDataUpdateParams { - /** - * Path param: The ID of the user to set account data for. The access token must be - * authorized to make requests for this user ID. - */ - userId: string; - - /** - * Body param - */ - body: unknown; -} - -export declare namespace AccountData { - export { - type AccountDataRetrieveResponse as AccountDataRetrieveResponse, - type AccountDataUpdateResponse as AccountDataUpdateResponse, - type AccountDataRetrieveParams as AccountDataRetrieveParams, - type AccountDataUpdateParams as AccountDataUpdateParams, - }; -} diff --git a/src/resources/matrix/users/index.ts b/src/resources/matrix/users/index.ts deleted file mode 100644 index f7d0405c..00000000 --- a/src/resources/matrix/users/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -export { - AccountData, - BaseAccountData, - type AccountDataRetrieveResponse, - type AccountDataUpdateResponse, - type AccountDataRetrieveParams, - type AccountDataUpdateParams, -} from './account-data'; -export { Users, BaseUsers, type UserRetrieveProfileResponse } from './users'; diff --git a/src/resources/matrix/users/users.ts b/src/resources/matrix/users/users.ts deleted file mode 100644 index 8fd4e3a6..00000000 --- a/src/resources/matrix/users/users.ts +++ /dev/null @@ -1,71 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { APIResource } from '../../../core/resource'; -import * as AccountDataAPI from './account-data'; -import { - AccountData, - AccountDataRetrieveParams, - AccountDataRetrieveResponse, - AccountDataUpdateParams, - AccountDataUpdateResponse, - BaseAccountData, -} from './account-data'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; - -export class BaseUsers extends APIResource { - static override readonly _key: readonly ['matrix', 'users'] = Object.freeze(['matrix', 'users'] as const); - - /** - * Get the complete profile for a user. - * - * @example - * ```ts - * const response = await client.matrix.users.retrieveProfile( - * '@alice:example.com', - * ); - * ``` - */ - retrieveProfile(userID: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/_matrix/client/v3/profile/${userID}`, options); - } -} -export class Users extends BaseUsers { - accountData: AccountDataAPI.AccountData = new AccountDataAPI.AccountData(this._client); -} - -export interface UserRetrieveProfileResponse { - /** - * The user's avatar URL if they have set one, otherwise not present. - */ - avatar_url?: string; - - /** - * The user's display name if they have set one, otherwise not present. - */ - displayname?: string; - - /** - * The user's time zone. - */ - 'm.tz'?: string; - - [k: string]: unknown; -} - -Users.AccountData = AccountData; -Users.BaseAccountData = BaseAccountData; - -export declare namespace Users { - export { type UserRetrieveProfileResponse as UserRetrieveProfileResponse }; - - export { - AccountData as AccountData, - BaseAccountData as BaseAccountData, - type AccountDataRetrieveResponse as AccountDataRetrieveResponse, - type AccountDataUpdateResponse as AccountDataUpdateResponse, - type AccountDataRetrieveParams as AccountDataRetrieveParams, - type AccountDataUpdateParams as AccountDataUpdateParams, - }; -} diff --git a/src/resources/shared.ts b/src/resources/shared.ts index 82735239..f5f34e6b 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -2,11 +2,19 @@ import { CursorNoLimit, CursorSearch } from '../core/pagination'; +export interface APIError { + code: string; + + message: string; + + details?: { [key: string]: unknown }; +} + export interface AppStateSnapshot { /** * Encrypted messaging setup status. */ - e2ee: AppStateSnapshot.E2ee; + e2ee: AppStateSnapshot.E2EE; /** * Current onboarding state for Beeper Desktop. @@ -35,7 +43,7 @@ export namespace AppStateSnapshot { /** * Encrypted messaging setup status. */ - export interface E2ee { + export interface E2EE { /** * Whether this account can verify trusted devices. */ @@ -49,7 +57,7 @@ export namespace AppStateSnapshot { /** * Whether the user confirmed that they saved their recovery key. */ - hasBackedUpCode: boolean; + hasBackedUpRecoveryKey: boolean; /** * Whether encrypted messaging setup has started. @@ -64,7 +72,7 @@ export namespace AppStateSnapshot { /** * Encrypted messaging keys available on this device. */ - secrets: E2ee.Secrets; + secrets: E2EE.Secrets; /** * Whether secure key storage is available. @@ -79,10 +87,10 @@ export namespace AppStateSnapshot { /** * Unix timestamp for when the recovery key was created. */ - recoveryCodeGeneratedAt?: number; + recoveryKeyGeneratedAt?: number; } - export namespace E2ee { + export namespace E2EE { /** * Encrypted messaging keys available on this device. */ @@ -100,7 +108,7 @@ export namespace AppStateSnapshot { /** * Whether a recovery key is available. */ - recoveryCode: boolean; + recoveryKey: boolean; /** * Whether the device trust key is available. @@ -139,61 +147,59 @@ export namespace AppStateSnapshot { */ export interface Verification { /** - * Verification actions that are valid for the current state. + * Verification ID to pass in verification action paths. */ - availableActions: Array< - 'create' | 'qr.scan' | 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm' - >; + id: string; /** - * Current trusted-device verification state. + * Verification actions that are valid for the current state. */ - state: 'idle' | 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; /** - * Verification error details, if verification stopped. + * Whether this device started or received the verification. */ - error?: Verification.Error; + direction: 'incoming' | 'outgoing'; /** - * User ID that started verification. + * Verification methods supported for this transaction. */ - from?: string; + methods: Array<'qr' | 'sas'>; /** - * Device that started verification. + * Why this verification exists. */ - fromDevice?: string; + purpose: 'login' | 'device'; /** - * Other device participating in verification. + * Current trusted-device verification state. */ - otherDevice?: string; + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; /** - * QR code payload to display for verification. + * Verification error details, if verification stopped. */ - qrData?: string; + error?: Verification.Error; /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - sas?: Verification.Sas; + otherDevice?: Verification.OtherDevice; /** - * Whether emoji comparison is available. + * Other user participating in verification. */ - supportsSAS?: boolean; + otherUserID?: string; /** - * Whether QR code verification is available. + * QR verification data. */ - supportsScanQRCode?: boolean; + qr?: Verification.Qr; /** - * Verification ID to pass in verification action paths. + * Emoji or number comparison data for verification. */ - verificationID?: string; + sas?: Verification.SAS; } export namespace Verification { @@ -213,18 +219,43 @@ export namespace AppStateSnapshot { } /** - * Emoji or number comparison data for verification. + * Other device participating in verification. */ - export interface Sas { + export interface OtherDevice { /** - * Number sequence to compare on both devices. + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. */ - decimals: string; + data: string; + } + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { /** * Emoji sequence to compare on both devices. */ emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; } } } diff --git a/tests/api-resources/accounts/accounts.test.ts b/tests/api-resources/accounts/accounts.test.ts index aa78a863..d8a98efa 100644 --- a/tests/api-resources/accounts/accounts.test.ts +++ b/tests/api-resources/accounts/accounts.test.ts @@ -17,6 +17,17 @@ const partialClient = createClient({ }); const runTests = (client: PartialBeeperDesktop<{ accounts: BaseAccounts }>) => { + test('retrieve', async () => { + const responsePromise = client.accounts.retrieve('accountID'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + test('list', async () => { const responsePromise = client.accounts.list(); const rawResponse = await responsePromise.asResponse(); diff --git a/tests/api-resources/app/app.test.ts b/tests/api-resources/app/app.test.ts index b501ff17..d433c3b1 100644 --- a/tests/api-resources/app/app.test.ts +++ b/tests/api-resources/app/app.test.ts @@ -17,8 +17,8 @@ const partialClient = createClient({ }); const runTests = (client: PartialBeeperDesktop<{ app: BaseApp }>) => { - test('status', async () => { - const responsePromise = client.app.status(); + test('session', async () => { + const responsePromise = client.app.session(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; diff --git a/tests/api-resources/app/e2ee/recovery-code/recovery-code.test.ts b/tests/api-resources/app/e2ee/recovery-code/recovery-code.test.ts deleted file mode 100644 index e433cef7..00000000 --- a/tests/api-resources/app/e2ee/recovery-code/recovery-code.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { E2ee } from '@beeper/desktop-api/resources/app/e2ee/e2ee'; -import { BaseRecoveryCode } from '@beeper/desktop-api/resources/app/e2ee/recovery-code/recovery-code'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseRecoveryCode], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [E2ee], -}); - -const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { recoveryCode: BaseRecoveryCode } } }>) => { - test('markBackedUp', async () => { - const responsePromise = client.app.e2ee.recoveryCode.markBackedUp(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('verify: only required params', async () => { - const responsePromise = client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('verify: required and optional params', async () => { - const response = await client.app.e2ee.recoveryCode.verify({ recoveryCode: 'x' }); - }); -}; -describe('resource recoveryCode', () => runTests(client)); -describe('resource recoveryCode (tree shakable, base)', () => runTests(partialClient)); -describe('resource recoveryCode (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/login.test.ts b/tests/api-resources/app/login/login.test.ts similarity index 99% rename from tests/api-resources/app/login.test.ts rename to tests/api-resources/app/login/login.test.ts index d0458efb..1e1492fe 100644 --- a/tests/api-resources/app/login.test.ts +++ b/tests/api-resources/app/login/login.test.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { App } from '@beeper/desktop-api/resources/app/app'; -import { BaseLogin } from '@beeper/desktop-api/resources/app/login'; +import { BaseLogin } from '@beeper/desktop-api/resources/app/login/login'; import BeeperDesktop from '@beeper/desktop-api'; import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; diff --git a/tests/api-resources/matrix/bridges/capabilities.test.ts b/tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts similarity index 53% rename from tests/api-resources/matrix/bridges/capabilities.test.ts rename to tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts index a24bbb1a..e54a0559 100644 --- a/tests/api-resources/matrix/bridges/capabilities.test.ts +++ b/tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; -import { BaseCapabilities } from '@beeper/desktop-api/resources/matrix/bridges/capabilities'; +import { Verification } from '@beeper/desktop-api/resources/app/login/verification/verification'; +import { BaseRecoveryKey } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/recovery-key'; import BeeperDesktop from '@beeper/desktop-api'; import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; @@ -14,20 +14,20 @@ const client = new BeeperDesktop({ const partialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseCapabilities], + resources: [BaseRecoveryKey], }); const parentPartialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Bridges], + resources: [Verification], }); const runTests = ( - client: PartialBeeperDesktop<{ matrix: { bridges: { capabilities: BaseCapabilities } } }>, + client: PartialBeeperDesktop<{ app: { login: { verification: { recoveryKey: BaseRecoveryKey } } } }>, ) => { - test('retrieve', async () => { - const responsePromise = client.matrix.bridges.capabilities.retrieve('bridgeID'); + test('verify: only required params', async () => { + const responsePromise = client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -36,7 +36,11 @@ const runTests = ( expect(dataAndResponse.data).toBe(response); expect(dataAndResponse.response).toBe(rawResponse); }); + + test('verify: required and optional params', async () => { + const response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' }); + }); }; -describe('resource capabilities', () => runTests(client)); -describe('resource capabilities (tree shakable, base)', () => runTests(partialClient)); -describe('resource capabilities (tree shakable, subresource)', () => runTests(parentPartialClient)); +describe('resource recoveryKey', () => runTests(client)); +describe('resource recoveryKey (tree shakable, base)', () => runTests(partialClient)); +describe('resource recoveryKey (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/e2ee/recovery-code/reset.test.ts b/tests/api-resources/app/login/verification/recovery-key/reset.test.ts similarity index 74% rename from tests/api-resources/app/e2ee/recovery-code/reset.test.ts rename to tests/api-resources/app/login/verification/recovery-key/reset.test.ts index b2985000..178d978b 100644 --- a/tests/api-resources/app/e2ee/recovery-code/reset.test.ts +++ b/tests/api-resources/app/login/verification/recovery-key/reset.test.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { RecoveryCode } from '@beeper/desktop-api/resources/app/e2ee/recovery-code/recovery-code'; -import { BaseReset } from '@beeper/desktop-api/resources/app/e2ee/recovery-code/reset'; +import { RecoveryKey } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/recovery-key'; +import { BaseReset } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/reset'; import BeeperDesktop from '@beeper/desktop-api'; import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; @@ -20,14 +20,14 @@ const partialClient = createClient({ const parentPartialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [RecoveryCode], + resources: [RecoveryKey], }); const runTests = ( - client: PartialBeeperDesktop<{ app: { e2ee: { recoveryCode: { reset: BaseReset } } } }>, + client: PartialBeeperDesktop<{ app: { login: { verification: { recoveryKey: { reset: BaseReset } } } } }>, ) => { test('create', async () => { - const responsePromise = client.app.e2ee.recoveryCode.reset.create(); + const responsePromise = client.app.login.verification.recoveryKey.reset.create(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -40,15 +40,15 @@ const runTests = ( test('create: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( - client.app.e2ee.recoveryCode.reset.create( - { recoveryCode: 'recoveryCode' }, + client.app.login.verification.recoveryKey.reset.create( + { existingRecoveryKey: 'existingRecoveryKey' }, { path: '/_stainless_unknown_path' }, ), ).rejects.toThrow(BeeperDesktop.NotFoundError); }); test('confirm: only required params', async () => { - const responsePromise = client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' }); + const responsePromise = client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -59,7 +59,7 @@ const runTests = ( }); test('confirm: required and optional params', async () => { - const response = await client.app.e2ee.recoveryCode.reset.confirm({ recoveryCode: 'x' }); + const response = await client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' }); }); }; describe('resource reset', () => runTests(client)); diff --git a/tests/api-resources/app/e2ee/verification/qr.test.ts b/tests/api-resources/app/verifications/qr.test.ts similarity index 76% rename from tests/api-resources/app/e2ee/verification/qr.test.ts rename to tests/api-resources/app/verifications/qr.test.ts index 681906e4..fc09226d 100644 --- a/tests/api-resources/app/e2ee/verification/qr.test.ts +++ b/tests/api-resources/app/verifications/qr.test.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { BaseQr } from '@beeper/desktop-api/resources/app/e2ee/verification/qr'; -import { Verification } from '@beeper/desktop-api/resources/app/e2ee/verification/verification'; +import { BaseQr } from '@beeper/desktop-api/resources/app/verifications/qr'; +import { Verifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; import BeeperDesktop from '@beeper/desktop-api'; import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; @@ -20,12 +20,12 @@ const partialClient = createClient({ const parentPartialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Verification], + resources: [Verifications], }); -const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: { qr: BaseQr } } } }>) => { +const runTests = (client: PartialBeeperDesktop<{ app: { verifications: { qr: BaseQr } } }>) => { test('confirmScanned', async () => { - const responsePromise = client.app.e2ee.verification.qr.confirmScanned('x'); + const responsePromise = client.app.verifications.qr.confirmScanned('x'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -36,7 +36,7 @@ const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: { }); test('scan: only required params', async () => { - const responsePromise = client.app.e2ee.verification.qr.scan({ data: 'x' }); + const responsePromise = client.app.verifications.qr.scan({ data: 'x' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -47,7 +47,7 @@ const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: { }); test('scan: required and optional params', async () => { - const response = await client.app.e2ee.verification.qr.scan({ data: 'x' }); + const response = await client.app.verifications.qr.scan({ data: 'x' }); }); }; describe('resource qr', () => runTests(client)); diff --git a/tests/api-resources/app/e2ee/verification/sas.test.ts b/tests/api-resources/app/verifications/sas.test.ts similarity index 77% rename from tests/api-resources/app/e2ee/verification/sas.test.ts rename to tests/api-resources/app/verifications/sas.test.ts index d800bf63..5564a785 100644 --- a/tests/api-resources/app/e2ee/verification/sas.test.ts +++ b/tests/api-resources/app/verifications/sas.test.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { BaseSas } from '@beeper/desktop-api/resources/app/e2ee/verification/sas'; -import { Verification } from '@beeper/desktop-api/resources/app/e2ee/verification/verification'; +import { BaseSAS } from '@beeper/desktop-api/resources/app/verifications/sas'; +import { Verifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; import BeeperDesktop from '@beeper/desktop-api'; import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; @@ -14,18 +14,18 @@ const client = new BeeperDesktop({ const partialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseSas], + resources: [BaseSAS], }); const parentPartialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Verification], + resources: [Verifications], }); -const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: { sas: BaseSas } } } }>) => { +const runTests = (client: PartialBeeperDesktop<{ app: { verifications: { sas: BaseSAS } } }>) => { test('confirm', async () => { - const responsePromise = client.app.e2ee.verification.sas.confirm('x'); + const responsePromise = client.app.verifications.sas.confirm('x'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -36,7 +36,7 @@ const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: { }); test('start', async () => { - const responsePromise = client.app.e2ee.verification.sas.start('x'); + const responsePromise = client.app.verifications.sas.start('x'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; diff --git a/tests/api-resources/app/verifications/verifications.test.ts b/tests/api-resources/app/verifications/verifications.test.ts new file mode 100644 index 00000000..076b9daf --- /dev/null +++ b/tests/api-resources/app/verifications/verifications.test.ts @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { App } from '@beeper/desktop-api/resources/app/app'; +import { BaseVerifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseVerifications], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [App], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { verifications: BaseVerifications } }>) => { + test('create', async () => { + const responsePromise = client.app.verifications.create(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.app.verifications.create( + { purpose: 'login', userID: 'userID' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); + + test('retrieve', async () => { + const responsePromise = client.app.verifications.retrieve('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list', async () => { + const responsePromise = client.app.verifications.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('accept', async () => { + const responsePromise = client.app.verifications.accept('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('cancel', async () => { + const responsePromise = client.app.verifications.cancel('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('cancel: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.app.verifications.cancel( + 'x', + { code: 'code', reason: 'reason' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); +}; +describe('resource verifications', () => runTests(client)); +describe('resource verifications (tree shakable, base)', () => runTests(partialClient)); +describe('resource verifications (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/bridges.test.ts b/tests/api-resources/bridges.test.ts deleted file mode 100644 index 51c139fc..00000000 --- a/tests/api-resources/bridges.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { BaseBridges } from '@beeper/desktop-api/resources/bridges'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseBridges], -}); - -const runTests = (client: PartialBeeperDesktop<{ bridges: BaseBridges }>) => { - test('list', async () => { - const responsePromise = client.bridges.list(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}; -describe('resource bridges', () => runTests(client)); -describe('resource bridges (tree shakable, base)', () => runTests(partialClient)); diff --git a/tests/api-resources/matrix/rooms/rooms.test.ts b/tests/api-resources/bridges/bridges.test.ts similarity index 63% rename from tests/api-resources/matrix/rooms/rooms.test.ts rename to tests/api-resources/bridges/bridges.test.ts index 1eb928db..8fae5c39 100644 --- a/tests/api-resources/matrix/rooms/rooms.test.ts +++ b/tests/api-resources/bridges/bridges.test.ts @@ -1,7 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Matrix } from '@beeper/desktop-api/resources/matrix/matrix'; -import { BaseRooms } from '@beeper/desktop-api/resources/matrix/rooms/rooms'; +import { BaseBridges } from '@beeper/desktop-api/resources/bridges/bridges'; import BeeperDesktop from '@beeper/desktop-api'; import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; @@ -14,18 +13,12 @@ const client = new BeeperDesktop({ const partialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseRooms], + resources: [BaseBridges], }); -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Matrix], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: BaseRooms } }>) => { - test('create', async () => { - const responsePromise = client.matrix.rooms.create({}); +const runTests = (client: PartialBeeperDesktop<{ bridges: BaseBridges }>) => { + test('retrieve', async () => { + const responsePromise = client.bridges.retrieve('local-whatsapp'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -35,8 +28,8 @@ const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: BaseRooms } }> expect(dataAndResponse.response).toBe(rawResponse); }); - test('join', async () => { - const responsePromise = client.matrix.rooms.join('!monkeys:matrix.org', {}); + test('list', async () => { + const responsePromise = client.bridges.list(); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -46,8 +39,8 @@ const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: BaseRooms } }> expect(dataAndResponse.response).toBe(rawResponse); }); - test('leave', async () => { - const responsePromise = client.matrix.rooms.leave('!nkl290a:matrix.org', {}); + test('retrieveCapabilities', async () => { + const responsePromise = client.bridges.retrieveCapabilities('local-whatsapp'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -57,6 +50,5 @@ const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: BaseRooms } }> expect(dataAndResponse.response).toBe(rawResponse); }); }; -describe('resource rooms', () => runTests(client)); -describe('resource rooms (tree shakable, base)', () => runTests(partialClient)); -describe('resource rooms (tree shakable, subresource)', () => runTests(parentPartialClient)); +describe('resource bridges', () => runTests(client)); +describe('resource bridges (tree shakable, base)', () => runTests(partialClient)); diff --git a/tests/api-resources/bridges/connections.test.ts b/tests/api-resources/bridges/connections.test.ts new file mode 100644 index 00000000..f08aaa25 --- /dev/null +++ b/tests/api-resources/bridges/connections.test.ts @@ -0,0 +1,80 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Bridges } from '@beeper/desktop-api/resources/bridges/bridges'; +import { BaseConnections } from '@beeper/desktop-api/resources/bridges/connections'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseConnections], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Bridges], +}); + +const runTests = (client: PartialBeeperDesktop<{ bridges: { connections: BaseConnections } }>) => { + test('retrieve: only required params', async () => { + const responsePromise = client.bridges.connections.retrieve('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { + bridgeID: 'local-whatsapp', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('retrieve: required and optional params', async () => { + const response = await client.bridges.connections.retrieve('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { + bridgeID: 'local-whatsapp', + }); + }); + + test('list', async () => { + const responsePromise = client.bridges.connections.list('local-whatsapp'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('remove: only required params', async () => { + const responsePromise = client.bridges.connections.remove('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { + bridgeID: 'local-whatsapp', + scope: 'current-device', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('remove: required and optional params', async () => { + const response = await client.bridges.connections.remove('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { + bridgeID: 'local-whatsapp', + scope: 'current-device', + }); + }); +}; +describe('resource connections', () => runTests(client)); +describe('resource connections (tree shakable, base)', () => runTests(partialClient)); +describe('resource connections (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/users/users.test.ts b/tests/api-resources/bridges/login-flows.test.ts similarity index 61% rename from tests/api-resources/matrix/users/users.test.ts rename to tests/api-resources/bridges/login-flows.test.ts index e38005c5..50d9280c 100644 --- a/tests/api-resources/matrix/users/users.test.ts +++ b/tests/api-resources/bridges/login-flows.test.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { Matrix } from '@beeper/desktop-api/resources/matrix/matrix'; -import { BaseUsers } from '@beeper/desktop-api/resources/matrix/users/users'; +import { Bridges } from '@beeper/desktop-api/resources/bridges/bridges'; +import { BaseLoginFlows } from '@beeper/desktop-api/resources/bridges/login-flows'; import BeeperDesktop from '@beeper/desktop-api'; import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; @@ -14,18 +14,18 @@ const client = new BeeperDesktop({ const partialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseUsers], + resources: [BaseLoginFlows], }); const parentPartialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Matrix], + resources: [Bridges], }); -const runTests = (client: PartialBeeperDesktop<{ matrix: { users: BaseUsers } }>) => { - test('retrieveProfile', async () => { - const responsePromise = client.matrix.users.retrieveProfile('@alice:example.com'); +const runTests = (client: PartialBeeperDesktop<{ bridges: { loginFlows: BaseLoginFlows } }>) => { + test('list', async () => { + const responsePromise = client.bridges.loginFlows.list('local-whatsapp'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -35,6 +35,6 @@ const runTests = (client: PartialBeeperDesktop<{ matrix: { users: BaseUsers } }> expect(dataAndResponse.response).toBe(rawResponse); }); }; -describe('resource users', () => runTests(client)); -describe('resource users (tree shakable, base)', () => runTests(partialClient)); -describe('resource users (tree shakable, subresource)', () => runTests(parentPartialClient)); +describe('resource loginFlows', () => runTests(client)); +describe('resource loginFlows (tree shakable, base)', () => runTests(partialClient)); +describe('resource loginFlows (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/e2ee/verification/verification.test.ts b/tests/api-resources/bridges/login-sessions/login-sessions.test.ts similarity index 59% rename from tests/api-resources/app/e2ee/verification/verification.test.ts rename to tests/api-resources/bridges/login-sessions/login-sessions.test.ts index 97dd2436..d0759efd 100644 --- a/tests/api-resources/app/e2ee/verification/verification.test.ts +++ b/tests/api-resources/bridges/login-sessions/login-sessions.test.ts @@ -1,7 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import { E2ee } from '@beeper/desktop-api/resources/app/e2ee/e2ee'; -import { BaseVerification } from '@beeper/desktop-api/resources/app/e2ee/verification/verification'; +import { Bridges } from '@beeper/desktop-api/resources/bridges/bridges'; +import { BaseLoginSessions } from '@beeper/desktop-api/resources/bridges/login-sessions/login-sessions'; import BeeperDesktop from '@beeper/desktop-api'; import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; @@ -14,18 +14,18 @@ const client = new BeeperDesktop({ const partialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseVerification], + resources: [BaseLoginSessions], }); const parentPartialClient = createClient({ accessToken: 'My Access Token', baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [E2ee], + resources: [Bridges], }); -const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: BaseVerification } } }>) => { +const runTests = (client: PartialBeeperDesktop<{ bridges: { loginSessions: BaseLoginSessions } }>) => { test('create', async () => { - const responsePromise = client.app.e2ee.verification.create(); + const responsePromise = client.bridges.loginSessions.create('local-whatsapp'); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -38,12 +38,20 @@ const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: Ba test('create: request options and params are passed correctly', async () => { // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error await expect( - client.app.e2ee.verification.create({ userID: 'userID' }, { path: '/_stainless_unknown_path' }), + client.bridges.loginSessions.create( + 'local-whatsapp', + { + accountID: 'accountID', + flowID: 'flowID', + loginID: 'loginID', + }, + { path: '/_stainless_unknown_path' }, + ), ).rejects.toThrow(BeeperDesktop.NotFoundError); }); - test('accept', async () => { - const responsePromise = client.app.e2ee.verification.accept('x'); + test('retrieve: only required params', async () => { + const responsePromise = client.bridges.loginSessions.retrieve('123', { bridgeID: 'local-whatsapp' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -53,8 +61,12 @@ const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: Ba expect(dataAndResponse.response).toBe(rawResponse); }); - test('cancel', async () => { - const responsePromise = client.app.e2ee.verification.cancel('x'); + test('retrieve: required and optional params', async () => { + const response = await client.bridges.loginSessions.retrieve('123', { bridgeID: 'local-whatsapp' }); + }); + + test('cancel: only required params', async () => { + const responsePromise = client.bridges.loginSessions.cancel('123', { bridgeID: 'local-whatsapp' }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -64,17 +76,10 @@ const runTests = (client: PartialBeeperDesktop<{ app: { e2ee: { verification: Ba expect(dataAndResponse.response).toBe(rawResponse); }); - test('cancel: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.app.e2ee.verification.cancel( - 'x', - { code: 'code', reason: 'reason' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(BeeperDesktop.NotFoundError); + test('cancel: required and optional params', async () => { + const response = await client.bridges.loginSessions.cancel('123', { bridgeID: 'local-whatsapp' }); }); }; -describe('resource verification', () => runTests(client)); -describe('resource verification (tree shakable, base)', () => runTests(partialClient)); -describe('resource verification (tree shakable, subresource)', () => runTests(parentPartialClient)); +describe('resource loginSessions', () => runTests(client)); +describe('resource loginSessions (tree shakable, base)', () => runTests(partialClient)); +describe('resource loginSessions (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/bridges/login-sessions/steps.test.ts b/tests/api-resources/bridges/login-sessions/steps.test.ts new file mode 100644 index 00000000..8d742efb --- /dev/null +++ b/tests/api-resources/bridges/login-sessions/steps.test.ts @@ -0,0 +1,55 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { LoginSessions } from '@beeper/desktop-api/resources/bridges/login-sessions/login-sessions'; +import { BaseSteps } from '@beeper/desktop-api/resources/bridges/login-sessions/steps'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseSteps], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [LoginSessions], +}); + +const runTests = (client: PartialBeeperDesktop<{ bridges: { loginSessions: { steps: BaseSteps } } }>) => { + test('submit: only required params', async () => { + const responsePromise = client.bridges.loginSessions.steps.submit('x', { + bridgeID: 'local-whatsapp', + loginSessionID: '123', + type: 'user_input', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('submit: required and optional params', async () => { + const response = await client.bridges.loginSessions.steps.submit('x', { + bridgeID: 'local-whatsapp', + loginSessionID: '123', + type: 'user_input', + fields: { foo: 'string' }, + lastURL: 'lastURL', + source: 'api', + }); + }); +}; +describe('resource steps', () => runTests(client)); +describe('resource steps (tree shakable, base)', () => runTests(partialClient)); +describe('resource steps (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/bridges/auth.test.ts b/tests/api-resources/matrix/bridges/auth.test.ts deleted file mode 100644 index 30a7964c..00000000 --- a/tests/api-resources/matrix/bridges/auth.test.ts +++ /dev/null @@ -1,166 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { BaseAuth } from '@beeper/desktop-api/resources/matrix/bridges/auth'; -import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseAuth], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Bridges], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { bridges: { auth: BaseAuth } } }>) => { - test('listFlows', async () => { - const responsePromise = client.matrix.bridges.auth.listFlows('bridgeID'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('listLogins', async () => { - const responsePromise = client.matrix.bridges.auth.listLogins('bridgeID'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('logout: only required params', async () => { - const responsePromise = client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', { - bridgeID: 'bridgeID', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('logout: required and optional params', async () => { - const response = await client.matrix.bridges.auth.logout('bcc68892-b180-414f-9516-b4aadf7d0496', { - bridgeID: 'bridgeID', - }); - }); - - test('startLogin: only required params', async () => { - const responsePromise = client.matrix.bridges.auth.startLogin('qr', { bridgeID: 'bridgeID' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('startLogin: required and optional params', async () => { - const response = await client.matrix.bridges.auth.startLogin('qr', { - bridgeID: 'bridgeID', - login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', - }); - }); - - test('submitCookies: only required params', async () => { - const responsePromise = client.matrix.bridges.auth.submitCookies('stepID', { - bridgeID: 'bridgeID', - loginProcessID: 'loginProcessID', - body: { foo: 'string' }, - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('submitCookies: required and optional params', async () => { - const response = await client.matrix.bridges.auth.submitCookies('stepID', { - bridgeID: 'bridgeID', - loginProcessID: 'loginProcessID', - body: { foo: 'string' }, - }); - }); - - test('submitUserInput: only required params', async () => { - const responsePromise = client.matrix.bridges.auth.submitUserInput('stepID', { - bridgeID: 'bridgeID', - loginProcessID: 'loginProcessID', - body: { foo: 'string' }, - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('submitUserInput: required and optional params', async () => { - const response = await client.matrix.bridges.auth.submitUserInput('stepID', { - bridgeID: 'bridgeID', - loginProcessID: 'loginProcessID', - body: { foo: 'string' }, - }); - }); - - test('waitForStep: only required params', async () => { - const responsePromise = client.matrix.bridges.auth.waitForStep('stepID', { - bridgeID: 'bridgeID', - loginProcessID: 'loginProcessID', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('waitForStep: required and optional params', async () => { - const response = await client.matrix.bridges.auth.waitForStep('stepID', { - bridgeID: 'bridgeID', - loginProcessID: 'loginProcessID', - }); - }); - - test('whoami', async () => { - const responsePromise = client.matrix.bridges.auth.whoami('bridgeID'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}; -describe('resource auth', () => runTests(client)); -describe('resource auth (tree shakable, base)', () => runTests(partialClient)); -describe('resource auth (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/bridges/contacts.test.ts b/tests/api-resources/matrix/bridges/contacts.test.ts deleted file mode 100644 index 1e669c23..00000000 --- a/tests/api-resources/matrix/bridges/contacts.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; -import { BaseContacts } from '@beeper/desktop-api/resources/matrix/bridges/contacts'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseContacts], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Bridges], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { bridges: { contacts: BaseContacts } } }>) => { - test('list', async () => { - const responsePromise = client.matrix.bridges.contacts.list('bridgeID'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('list: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.matrix.bridges.contacts.list( - 'bridgeID', - { login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(BeeperDesktop.NotFoundError); - }); -}; -describe('resource contacts', () => runTests(client)); -describe('resource contacts (tree shakable, base)', () => runTests(partialClient)); -describe('resource contacts (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/bridges/rooms.test.ts b/tests/api-resources/matrix/bridges/rooms.test.ts deleted file mode 100644 index e574d381..00000000 --- a/tests/api-resources/matrix/bridges/rooms.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; -import { BaseRooms } from '@beeper/desktop-api/resources/matrix/bridges/rooms'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseRooms], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Bridges], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { bridges: { rooms: BaseRooms } } }>) => { - test('createDm: only required params', async () => { - const responsePromise = client.matrix.bridges.rooms.createDm('identifier', { bridgeID: 'bridgeID' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('createDm: required and optional params', async () => { - const response = await client.matrix.bridges.rooms.createDm('identifier', { - bridgeID: 'bridgeID', - login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', - }); - }); - - test('createGroup: only required params', async () => { - const responsePromise = client.matrix.bridges.rooms.createGroup('groupType', { bridgeID: 'bridgeID' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('createGroup: required and optional params', async () => { - const response = await client.matrix.bridges.rooms.createGroup('groupType', { - bridgeID: 'bridgeID', - login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', - avatar: { url: 'url' }, - disappear: { timer: 0, type: 'type' }, - name: { name: 'name' }, - parent: {}, - participants: ['string'], - room_id: 'room_id', - topic: { topic: 'topic' }, - type: 'channel', - username: 'username', - }); - }); -}; -describe('resource rooms', () => runTests(client)); -describe('resource rooms (tree shakable, base)', () => runTests(partialClient)); -describe('resource rooms (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/bridges/users.test.ts b/tests/api-resources/matrix/bridges/users.test.ts deleted file mode 100644 index 1eb0476a..00000000 --- a/tests/api-resources/matrix/bridges/users.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Bridges } from '@beeper/desktop-api/resources/matrix/bridges/bridges'; -import { BaseUsers } from '@beeper/desktop-api/resources/matrix/bridges/users'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseUsers], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Bridges], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { bridges: { users: BaseUsers } } }>) => { - test('resolve: only required params', async () => { - const responsePromise = client.matrix.bridges.users.resolve('identifier', { bridgeID: 'bridgeID' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('resolve: required and optional params', async () => { - const response = await client.matrix.bridges.users.resolve('identifier', { - bridgeID: 'bridgeID', - login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', - }); - }); - - test('search', async () => { - const responsePromise = client.matrix.bridges.users.search('bridgeID'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('search: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.matrix.bridges.users.search( - 'bridgeID', - { login_id: 'bcc68892-b180-414f-9516-b4aadf7d0496', query: 'query' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(BeeperDesktop.NotFoundError); - }); -}; -describe('resource users', () => runTests(client)); -describe('resource users (tree shakable, base)', () => runTests(partialClient)); -describe('resource users (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/rooms/account-data.test.ts b/tests/api-resources/matrix/rooms/account-data.test.ts deleted file mode 100644 index da07e7ec..00000000 --- a/tests/api-resources/matrix/rooms/account-data.test.ts +++ /dev/null @@ -1,73 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { BaseAccountData } from '@beeper/desktop-api/resources/matrix/rooms/account-data'; -import { Rooms } from '@beeper/desktop-api/resources/matrix/rooms/rooms'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseAccountData], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Rooms], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: { accountData: BaseAccountData } } }>) => { - test('retrieve: only required params', async () => { - const responsePromise = client.matrix.rooms.accountData.retrieve('org.example.custom.room.config', { - userId: '@alice:example.com', - roomId: '!726s6s6q:example.com', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.matrix.rooms.accountData.retrieve('org.example.custom.room.config', { - userId: '@alice:example.com', - roomId: '!726s6s6q:example.com', - }); - }); - - test('update: only required params', async () => { - const responsePromise = client.matrix.rooms.accountData.update('org.example.custom.room.config', { - userId: '@alice:example.com', - roomId: '!726s6s6q:example.com', - body: { custom_account_data_key: 'custom_account_data_value' }, - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('update: required and optional params', async () => { - const response = await client.matrix.rooms.accountData.update('org.example.custom.room.config', { - userId: '@alice:example.com', - roomId: '!726s6s6q:example.com', - body: { custom_account_data_key: 'custom_account_data_value' }, - }); - }); -}; -describe('resource accountData', () => runTests(client)); -describe('resource accountData (tree shakable, base)', () => runTests(partialClient)); -describe('resource accountData (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/rooms/events.test.ts b/tests/api-resources/matrix/rooms/events.test.ts deleted file mode 100644 index 81bb6e08..00000000 --- a/tests/api-resources/matrix/rooms/events.test.ts +++ /dev/null @@ -1,48 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { BaseEvents } from '@beeper/desktop-api/resources/matrix/rooms/events'; -import { Rooms } from '@beeper/desktop-api/resources/matrix/rooms/rooms'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseEvents], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Rooms], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: { events: BaseEvents } } }>) => { - test('retrieve: only required params', async () => { - const responsePromise = client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', { - roomId: '!636q39766251:matrix.org', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.matrix.rooms.events.retrieve('$asfDuShaf7Gafaw:matrix.org', { - roomId: '!636q39766251:matrix.org', - }); - }); -}; -describe('resource events', () => runTests(client)); -describe('resource events (tree shakable, base)', () => runTests(partialClient)); -describe('resource events (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/rooms/state.test.ts b/tests/api-resources/matrix/rooms/state.test.ts deleted file mode 100644 index b44f7931..00000000 --- a/tests/api-resources/matrix/rooms/state.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Rooms } from '@beeper/desktop-api/resources/matrix/rooms/rooms'; -import { BaseState } from '@beeper/desktop-api/resources/matrix/rooms/state'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseState], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Rooms], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { rooms: { state: BaseState } } }>) => { - test('retrieve: only required params', async () => { - const responsePromise = client.matrix.rooms.state.retrieve('state_key', { - roomId: '!636q39766251:example.com', - eventType: 'm.room.name', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.matrix.rooms.state.retrieve('state_key', { - roomId: '!636q39766251:example.com', - eventType: 'm.room.name', - format: 'content', - }); - }); - - test('list', async () => { - const responsePromise = client.matrix.rooms.state.list('!636q39766251:example.com'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}; -describe('resource state', () => runTests(client)); -describe('resource state (tree shakable, base)', () => runTests(partialClient)); -describe('resource state (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/matrix/users/account-data.test.ts b/tests/api-resources/matrix/users/account-data.test.ts deleted file mode 100644 index 21210e6f..00000000 --- a/tests/api-resources/matrix/users/account-data.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { BaseAccountData } from '@beeper/desktop-api/resources/matrix/users/account-data'; -import { Users } from '@beeper/desktop-api/resources/matrix/users/users'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseAccountData], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Users], -}); - -const runTests = (client: PartialBeeperDesktop<{ matrix: { users: { accountData: BaseAccountData } } }>) => { - test('retrieve: only required params', async () => { - const responsePromise = client.matrix.users.accountData.retrieve('org.example.custom.config', { - userId: '@alice:example.com', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.matrix.users.accountData.retrieve('org.example.custom.config', { - userId: '@alice:example.com', - }); - }); - - test('update: only required params', async () => { - const responsePromise = client.matrix.users.accountData.update('org.example.custom.config', { - userId: '@alice:example.com', - body: { custom_account_data_key: 'custom_config_value' }, - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('update: required and optional params', async () => { - const response = await client.matrix.users.accountData.update('org.example.custom.config', { - userId: '@alice:example.com', - body: { custom_account_data_key: 'custom_config_value' }, - }); - }); -}; -describe('resource accountData', () => runTests(client)); -describe('resource accountData (tree shakable, base)', () => runTests(partialClient)); -describe('resource accountData (tree shakable, subresource)', () => runTests(parentPartialClient)); From 8b59f3a10dc81df3e61d1d467f221edf4fc2d032 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 17 May 2026 16:32:04 +0000 Subject: [PATCH 11/17] chore(internal): regenerate SDK with no functional changes --- .stats.yml | 6 +- api.md | 91 - packages/mcp-server/src/code-tool-worker.ts | 20 - packages/mcp-server/src/local-docs-search.ts | 1026 +-------- packages/mcp-server/src/methods.ts | 120 - src/client.ts | 36 +- src/resources/accounts/accounts.ts | 25 +- src/resources/accounts/contacts.ts | 4 +- src/resources/app/app.ts | 1997 +---------------- src/resources/app/index.ts | 37 +- src/resources/app/login/index.ts | 12 +- src/resources/app/login/login.ts | 802 +------ src/resources/app/login/verification/index.ts | 7 +- .../login/verification/recovery-key/index.ts | 16 +- .../verification/recovery-key/recovery-key.ts | 307 +-- .../login/verification/recovery-key/reset.ts | 577 ----- .../app/login/verification/verification.ts | 14 +- src/resources/app/verifications/index.ts | 16 +- src/resources/app/verifications/qr.ts | 806 ------- src/resources/app/verifications/sas.ts | 795 ------- .../app/verifications/verifications.ts | 1762 +-------------- src/resources/assets.ts | 12 +- src/resources/bridges/bridges.ts | 283 ++- src/resources/bridges/connections.ts | 91 - src/resources/bridges/index.ts | 10 +- src/resources/bridges/login-flows.ts | 7 +- .../bridges/login-sessions/login-sessions.ts | 19 +- src/resources/bridges/login-sessions/steps.ts | 11 +- src/resources/chats/chats.ts | 52 +- src/resources/chats/messages/reactions.ts | 16 +- src/resources/chats/reminders.ts | 4 +- src/resources/index.ts | 14 +- src/resources/info.ts | 4 +- src/resources/messages.ts | 35 +- src/resources/shared.ts | 48 +- src/resources/top-level.ts | 4 +- tests/api-resources/app/app.test.ts | 32 - tests/api-resources/app/login/login.test.ts | 95 - .../recovery-key/recovery-key.test.ts | 46 - .../verification/recovery-key/reset.test.ts | 67 - .../app/verifications/qr.test.ts | 55 - .../app/verifications/sas.test.ts | 51 - .../app/verifications/verifications.test.ts | 105 - .../api-resources/bridges/connections.test.ts | 80 - .../login-sessions/login-sessions.test.ts | 6 +- 45 files changed, 444 insertions(+), 9179 deletions(-) delete mode 100644 tests/api-resources/app/app.test.ts delete mode 100644 tests/api-resources/app/login/login.test.ts delete mode 100644 tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts delete mode 100644 tests/api-resources/app/login/verification/recovery-key/reset.test.ts delete mode 100644 tests/api-resources/app/verifications/qr.test.ts delete mode 100644 tests/api-resources/app/verifications/sas.test.ts delete mode 100644 tests/api-resources/app/verifications/verifications.test.ts delete mode 100644 tests/api-resources/bridges/connections.test.ts diff --git a/.stats.yml b/.stats.yml index c490046e..f8d62378 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 59 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-85f9d588b888eaac24243e6b71c8ed3b57bba8b28d43bef94d590de60e2d8344.yml -openapi_spec_hash: 7c41d922ada4b7ef51dc0e70005d8d62 +configured_endpoints: 39 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-87df69f641d994f09669f77093988df0b13da380d36076964d4a2563e9ce202e.yml +openapi_spec_hash: 9de80d05f7562b7ecd07c466f0fdf58b config_hash: 2ebcc80e2cbd2342e132f4474ec24212 diff --git a/api.md b/api.md index 90409ce9..7537ea0b 100644 --- a/api.md +++ b/api.md @@ -52,7 +52,6 @@ Methods: Types: - Bridge -- BridgeConnection - CookieField - DisappearingTimerCapability - GroupFieldCapability @@ -83,17 +82,6 @@ Methods: ## Connections -Types: - -- ConnectionListResponse -- ConnectionRemoveResponse - -Methods: - -- client.bridges.connections.retrieve(loginID, { ...params }) -> BridgeConnection -- client.bridges.connections.list(bridgeID) -> ConnectionListResponse -- client.bridges.connections.remove(loginID, { ...params }) -> ConnectionRemoveResponse - ## LoginSessions Types: @@ -200,97 +188,18 @@ Methods: Types: -- LoginRegistrationRequiredResponse -- LoginResponse -- LoginResponseOutput -- RecoveryKeyResetResponse -- SessionMutationResponse - Verification -- VerificationResponse -- AppSessionResponse - -Methods: - -- client.app.session() -> AppSessionResponse ## Login -Types: - -- LoginEmailResponse -- LoginRegisterResponse -- LoginResponseResponse -- LoginStartResponse - -Methods: - -- client.app.login.email({ ...params }) -> unknown -- client.app.login.register({ ...params }) -> LoginRegisterResponse -- client.app.login.response({ ...params }) -> LoginResponseResponse -- client.app.login.start() -> LoginStartResponse - ### Verification #### RecoveryKey -Types: - -- RecoveryKeyVerifyResponse - -Methods: - -- client.app.login.verification.recoveryKey.verify({ ...params }) -> RecoveryKeyVerifyResponse - ##### Reset -Types: - -- ResetCreateResponse -- ResetConfirmResponse - -Methods: - -- client.app.login.verification.recoveryKey.reset.create({ ...params }) -> ResetCreateResponse -- client.app.login.verification.recoveryKey.reset.confirm({ ...params }) -> ResetConfirmResponse - ## Verifications -Types: - -- VerificationCreateResponse -- VerificationRetrieveResponse -- VerificationListResponse -- VerificationAcceptResponse -- VerificationCancelResponse - -Methods: - -- client.app.verifications.create({ ...params }) -> VerificationCreateResponse -- client.app.verifications.retrieve(verificationID) -> VerificationRetrieveResponse -- client.app.verifications.list() -> VerificationListResponse -- client.app.verifications.accept(verificationID) -> VerificationAcceptResponse -- client.app.verifications.cancel(verificationID, { ...params }) -> VerificationCancelResponse - ### Qr -Types: - -- QrConfirmScannedResponse -- QrScanResponse - -Methods: - -- client.app.verifications.qr.confirmScanned(verificationID) -> QrConfirmScannedResponse -- client.app.verifications.qr.scan({ ...params }) -> QrScanResponse - ### SAS - -Types: - -- SASConfirmResponse -- SASStartResponse - -Methods: - -- client.app.verifications.sas.confirm(verificationID) -> SASConfirmResponse -- client.app.verifications.sas.start(verificationID) -> SASStartResponse diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index efe17bd5..8005afd0 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -118,9 +118,6 @@ const fuse = new Fuse( 'client.bridges.retrieve', 'client.bridges.retrieveCapabilities', 'client.bridges.loginFlows.list', - 'client.bridges.connections.list', - 'client.bridges.connections.remove', - 'client.bridges.connections.retrieve', 'client.bridges.loginSessions.cancel', 'client.bridges.loginSessions.create', 'client.bridges.loginSessions.retrieve', @@ -150,23 +147,6 @@ const fuse = new Fuse( 'client.assets.upload', 'client.assets.uploadBase64', 'client.info.retrieve', - 'client.app.session', - 'client.app.login.email', - 'client.app.login.register', - 'client.app.login.response', - 'client.app.login.start', - 'client.app.login.verification.recoveryKey.verify', - 'client.app.login.verification.recoveryKey.reset.confirm', - 'client.app.login.verification.recoveryKey.reset.create', - 'client.app.verifications.accept', - 'client.app.verifications.cancel', - 'client.app.verifications.create', - 'client.app.verifications.list', - 'client.app.verifications.retrieve', - 'client.app.verifications.qr.confirmScanned', - 'client.app.verifications.qr.scan', - 'client.app.verifications.sas.confirm', - 'client.app.verifications.sas.start', ], { threshold: 1, shouldSort: true }, ); diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 6c2400db..1ccd7fed 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -56,7 +56,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: 'post', summary: 'Focus Beeper Desktop app', description: - 'Focus Beeper Desktop and optionally navigate to a specific chat, message, or pre-fill plain text and an image path.', + 'Focus Beeper Desktop and optionally open a specific chat, jump to a message, or pre-fill text and an image.', stainlessPath: '(resource) $client > (method) focus', qualified: 'client.focus', params: [ @@ -67,7 +67,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ ], response: '{ success: boolean; }', markdown: - "## focus\n\n`client.focus(chatID?: string, draftAttachmentPath?: string, draftText?: string, messageID?: string): { success: boolean; }`\n\n**post** `/v1/focus`\n\nFocus Beeper Desktop and optionally navigate to a specific chat, message, or pre-fill plain text and an image path.\n\n### Parameters\n\n- `chatID?: string`\n Optional Beeper chat ID (or local chat ID) to focus after opening the app. If omitted, only opens/focuses the app.\n\n- `draftAttachmentPath?: string`\n Optional image path to populate in the message input field.\n\n- `draftText?: string`\n Optional plain text to populate in the message input field.\n\n- `messageID?: string`\n Optional message ID. Jumps to that message in the chat when opening.\n\n### Returns\n\n- `{ success: boolean; }`\n Response indicating successful app focus action.\n\n - `success: boolean`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.focus();\n\nconsole.log(response);\n```", + "## focus\n\n`client.focus(chatID?: string, draftAttachmentPath?: string, draftText?: string, messageID?: string): { success: boolean; }`\n\n**post** `/v1/focus`\n\nFocus Beeper Desktop and optionally open a specific chat, jump to a message, or pre-fill text and an image.\n\n### Parameters\n\n- `chatID?: string`\n Optional Beeper chat ID (or local chat ID) to focus after opening the app. If omitted, only opens/focuses the app.\n\n- `draftAttachmentPath?: string`\n Optional local image path to populate in the message input field.\n\n- `draftText?: string`\n Optional plain text to populate in the message input field.\n\n- `messageID?: string`\n Optional message ID. Jumps to that message in the chat when opening.\n\n### Returns\n\n- `{ success: boolean; }`\n Response indicating successful app focus action.\n\n - `success: boolean`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.focus();\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.focus', @@ -105,14 +105,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: 'get', summary: 'Search', description: - 'Returns matching chats, participant name matches in groups, and the first page of messages in one call. Paginate messages via search-messages. Paginate chats via search-chats.', + 'Return matching chats, participant matches in group chats, and the first page of message results in one call. Use the dedicated chat and message search endpoints for pagination.', stainlessPath: '(resource) $client > (method) search', qualified: 'client.search', params: ['query: string;'], response: '{ results: { chats: object[]; in_groups: object[]; messages: { chats: object; hasMore: boolean; items: message[]; newestCursor: string; oldestCursor: string; }; }; }', markdown: - "## search\n\n`client.search(query: string): { results: object; }`\n\n**get** `/v1/search`\n\nReturns matching chats, participant name matches in groups, and the first page of messages in one call. Paginate messages via search-messages. Paginate chats via search-chats.\n\n### Parameters\n\n- `query: string`\n User-typed search text. Literal word matching (non-semantic).\n\n### Returns\n\n- `{ results: { chats: object[]; in_groups: object[]; messages: { chats: object; hasMore: boolean; items: message[]; newestCursor: string; oldestCursor: string; }; }; }`\n\n - `results: { chats: { id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }[]; in_groups: { id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }[]; messages: { chats: object; hasMore: boolean; items: { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }[]; newestCursor: string; oldestCursor: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.search({ query: 'x' });\n\nconsole.log(response);\n```", + "## search\n\n`client.search(query: string): { results: object; }`\n\n**get** `/v1/search`\n\nReturn matching chats, participant matches in group chats, and the first page of message results in one call. Use the dedicated chat and message search endpoints for pagination.\n\n### Parameters\n\n- `query: string`\n User-typed search text. Uses literal word matching.\n\n### Returns\n\n- `{ results: { chats: object[]; in_groups: object[]; messages: { chats: object; hasMore: boolean; items: message[]; newestCursor: string; oldestCursor: string; }; }; }`\n\n - `results: { chats: { id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }[]; in_groups: { id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }[]; messages: { chats: object; hasMore: boolean; items: { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }[]; newestCursor: string; oldestCursor: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.search({ query: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.search', @@ -148,15 +148,15 @@ const EMBEDDED_METHODS: MethodEntry[] = [ name: 'list', endpoint: '/v1/accounts', httpMethod: 'get', - summary: 'List Chat Accounts', + summary: 'List chat accounts', description: - 'List Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.', + 'List chat accounts connected to this Beeper Client API server, including bridge, network, user identity, and connection status.', stainlessPath: '(resource) accounts > (method) list', qualified: 'client.accounts.list', response: '{ accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]', markdown: - "## list\n\n`client.accounts.list(): object[]`\n\n**get** `/v1/accounts`\n\nList Chat Accounts connected to this Beeper Desktop instance, including bridge metadata and network identity.\n\n### Returns\n\n- `{ accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]`\n Accounts configured on this device. Includes accountID, bridge metadata, optional network name, and user identity.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);\n```", + "## list\n\n`client.accounts.list(): object[]`\n\n**get** `/v1/accounts`\n\nList chat accounts connected to this Beeper Client API server, including bridge, network, user identity, and connection status.\n\n### Returns\n\n- `{ accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]`\n Chat accounts configured on this device. Includes accountID, bridge metadata, optional network name, and user identity.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst accounts = await client.accounts.list();\n\nconsole.log(accounts);\n```", perLanguage: { typescript: { method: 'client.accounts.list', @@ -192,15 +192,15 @@ const EMBEDDED_METHODS: MethodEntry[] = [ name: 'retrieve', endpoint: '/v1/accounts/{accountID}', httpMethod: 'get', - summary: 'Get Chat Account', - description: 'Get one Chat Account connected to this Beeper Desktop instance.', + summary: 'Get chat account', + description: 'Get one chat account connected to this Beeper Client API server.', stainlessPath: '(resource) accounts > (method) retrieve', qualified: 'client.accounts.retrieve', params: ['accountID: string;'], response: "{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }", markdown: - "## retrieve\n\n`client.accounts.retrieve(accountID: string): { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n\n**get** `/v1/accounts/{accountID}`\n\nGet one Chat Account connected to this Beeper Desktop instance.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n### Returns\n\n- `{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n A chat account added to Beeper.\n\n - `accountID: string`\n - `bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }`\n - `status: string`\n - `user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n - `capabilities?: object`\n - `loginID?: string`\n - `network?: string`\n - `statusText?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst account = await client.accounts.retrieve('accountID');\n\nconsole.log(account);\n```", + "## retrieve\n\n`client.accounts.retrieve(accountID: string): { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n\n**get** `/v1/accounts/{accountID}`\n\nGet one chat account connected to this Beeper Client API server.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n### Returns\n\n- `{ accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n A chat account added to Beeper.\n\n - `accountID: string`\n - `bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }`\n - `status: string`\n - `user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n - `capabilities?: object`\n - `loginID?: string`\n - `network?: string`\n - `statusText?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst account = await client.accounts.retrieve('accountID');\n\nconsole.log(account);\n```", perLanguage: { typescript: { method: 'client.accounts.retrieve', @@ -246,7 +246,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }', markdown: - "## search\n\n`client.accounts.contacts.search(accountID: string, query: string): { items: user[]; }`\n\n**get** `/v1/accounts/{accountID}/contacts`\n\nSearch contacts on a specific account using merged account contacts, network search, and exact identifier lookup.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `query: string`\n Text to search users by. Network-specific behavior.\n\n### Returns\n\n- `{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }`\n\n - `items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response);\n```", + "## search\n\n`client.accounts.contacts.search(accountID: string, query: string): { items: user[]; }`\n\n**get** `/v1/accounts/{accountID}/contacts`\n\nSearch contacts on a specific account using merged account contacts, network search, and exact identifier lookup.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `query: string`\n Text to search contacts by. Matching behavior depends on the network.\n\n### Returns\n\n- `{ items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; }`\n\n - `items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.accounts.contacts.search('accountID', { query: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.accounts.contacts.search', @@ -297,7 +297,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }', markdown: - "## list\n\n`client.accounts.contacts.list(accountID: string, cursor?: string, direction?: 'after' | 'before', limit?: number, query?: string): { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n\n**get** `/v1/accounts/{accountID}/contacts/list`\n\nList merged contacts for a specific account with cursor-based pagination.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `limit?: number`\n Maximum contacts to return per page.\n\n- `query?: string`\n Optional search query for blended contact lookup.\n\n### Returns\n\n- `{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n User the account belongs to.\n\n - `id: string`\n - `cannotMessage?: boolean`\n - `email?: string`\n - `fullName?: string`\n - `imgURL?: string`\n - `isSelf?: boolean`\n - `phoneNumber?: string`\n - `username?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user);\n}\n```", + "## list\n\n`client.accounts.contacts.list(accountID: string, cursor?: string, direction?: 'after' | 'before', limit?: number, query?: string): { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n\n**get** `/v1/accounts/{accountID}/contacts/list`\n\nList merged contacts for a specific account with cursor-based pagination.\n\n### Parameters\n\n- `accountID: string`\n Account ID this resource belongs to.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `limit?: number`\n Maximum contacts to return per page.\n\n- `query?: string`\n Optional search query for contact lookup.\n\n### Returns\n\n- `{ id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n User the account belongs to.\n\n - `id: string`\n - `cannotMessage?: boolean`\n - `email?: string`\n - `fullName?: string`\n - `imgURL?: string`\n - `isSelf?: boolean`\n - `phoneNumber?: string`\n - `username?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const user of client.accounts.contacts.list('accountID')) {\n console.log(user);\n}\n```", perLanguage: { typescript: { method: 'client.accounts.contacts.list', @@ -334,15 +334,15 @@ const EMBEDDED_METHODS: MethodEntry[] = [ name: 'list', endpoint: '/v1/bridges', httpMethod: 'get', - summary: 'List bridges', + summary: 'List available bridges', description: - 'List bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.', + 'List available bridges. A bridge is a chat-network connector that can connect or reconnect chat accounts. Connected accounts use the same Account schema as GET /v1/accounts.', stainlessPath: '(resource) bridges > (method) list', qualified: 'client.bridges.list', response: "{ items: { id: string; accounts: account[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }[]; }", markdown: - "## list\n\n`client.bridges.list(): { items: bridge[]; }`\n\n**get** `/v1/bridges`\n\nList bridge-backed account types that can be shown in add-account flows, grouped with connected accounts that use the same Account schema as GET /v1/accounts.\n\n### Returns\n\n- `{ items: { id: string; accounts: account[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }[]; }`\n Bridge-backed account types and their connected accounts.\n\n - `items: { id: string; accounts: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges);\n```", + "## list\n\n`client.bridges.list(): { items: bridge[]; }`\n\n**get** `/v1/bridges`\n\nList available bridges. A bridge is a chat-network connector that can connect or reconnect chat accounts. Connected accounts use the same Account schema as GET /v1/accounts.\n\n### Returns\n\n- `{ items: { id: string; accounts: account[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }[]; }`\n Available bridges and their connected accounts.\n\n - `items: { id: string; accounts: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridges = await client.bridges.list();\n\nconsole.log(bridges);\n```", perLanguage: { typescript: { method: 'client.bridges.list', @@ -379,14 +379,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ endpoint: '/v1/bridges/{bridgeID}', httpMethod: 'get', summary: 'Get bridge', - description: 'Get one bridge-backed account type and the connected accounts that use it.', + description: 'Get one bridge, including the chat accounts connected through it.', stainlessPath: '(resource) bridges > (method) retrieve', qualified: 'client.bridges.retrieve', params: ['bridgeID: string;'], response: "{ id: string; accounts: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }", markdown: - "## retrieve\n\n`client.bridges.retrieve(bridgeID: string): { id: string; accounts: account[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }`\n\n**get** `/v1/bridges/{bridgeID}`\n\nGet one bridge-backed account type and the connected accounts that use it.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ id: string; accounts: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }`\n Bridge-backed account type that can be shown in add-account flows.\n\n - `id: string`\n - `accounts: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]`\n - `activeAccountCount: number`\n - `displayName: string`\n - `provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'`\n - `status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'`\n - `supportsMultipleAccounts: boolean`\n - `type: string`\n - `network?: string`\n - `statusText?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridge = await client.bridges.retrieve('local-whatsapp');\n\nconsole.log(bridge);\n```", + "## retrieve\n\n`client.bridges.retrieve(bridgeID: string): { id: string; accounts: account[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }`\n\n**get** `/v1/bridges/{bridgeID}`\n\nGet one bridge, including the chat accounts connected through it.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ id: string; accounts: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]; activeAccountCount: number; displayName: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; supportsMultipleAccounts: boolean; type: string; network?: string; statusText?: string; }`\n Available bridge that can connect or reconnect chat accounts.\n\n - `id: string`\n - `accounts: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }[]`\n - `activeAccountCount: number`\n - `displayName: string`\n - `provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'`\n - `status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'`\n - `supportsMultipleAccounts: boolean`\n - `type: string`\n - `network?: string`\n - `statusText?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridge = await client.bridges.retrieve('local-whatsapp');\n\nconsole.log(bridge);\n```", perLanguage: { typescript: { method: 'client.bridges.retrieve', @@ -424,14 +424,15 @@ const EMBEDDED_METHODS: MethodEntry[] = [ endpoint: '/v1/bridges/{bridgeID}/capabilities', httpMethod: 'get', summary: 'Get bridge capabilities', - description: 'Get bridgev2 provisioning capabilities for a bridge.', + description: + 'Get advanced network capabilities for a bridge. This endpoint is intended for clients that build custom connect or chat-creation flows.', stainlessPath: '(resource) bridges > (method) retrieve_capabilities', qualified: 'client.bridges.retrieveCapabilities', params: ['bridgeID: string;'], response: '{ group_creation: object; resolve_identifier: { any_phone: boolean; contact_list: boolean; create_dm: boolean; lookup_email: boolean; lookup_phone: boolean; lookup_username: boolean; search: boolean; }; image_pack_import?: boolean; }', markdown: - "## retrieve_capabilities\n\n`client.bridges.retrieveCapabilities(bridgeID: string): { group_creation: object; resolve_identifier: resolve_identifier_capabilities; image_pack_import?: boolean; }`\n\n**get** `/v1/bridges/{bridgeID}/capabilities`\n\nGet bridgev2 provisioning capabilities for a bridge.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ group_creation: object; resolve_identifier: { any_phone: boolean; contact_list: boolean; create_dm: boolean; lookup_email: boolean; lookup_phone: boolean; lookup_username: boolean; search: boolean; }; image_pack_import?: boolean; }`\n bridgev2 provisioning capabilities.\n\n - `group_creation: object`\n - `resolve_identifier: { any_phone: boolean; contact_list: boolean; create_dm: boolean; lookup_email: boolean; lookup_phone: boolean; lookup_username: boolean; search: boolean; }`\n - `image_pack_import?: boolean`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst provisioningCapabilities = await client.bridges.retrieveCapabilities('local-whatsapp');\n\nconsole.log(provisioningCapabilities);\n```", + "## retrieve_capabilities\n\n`client.bridges.retrieveCapabilities(bridgeID: string): { group_creation: object; resolve_identifier: resolve_identifier_capabilities; image_pack_import?: boolean; }`\n\n**get** `/v1/bridges/{bridgeID}/capabilities`\n\nGet advanced network capabilities for a bridge. This endpoint is intended for clients that build custom connect or chat-creation flows.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ group_creation: object; resolve_identifier: { any_phone: boolean; contact_list: boolean; create_dm: boolean; lookup_email: boolean; lookup_phone: boolean; lookup_username: boolean; search: boolean; }; image_pack_import?: boolean; }`\n Advanced network capabilities for account lookup and group creation.\n\n - `group_creation: object`\n - `resolve_identifier: { any_phone: boolean; contact_list: boolean; create_dm: boolean; lookup_email: boolean; lookup_phone: boolean; lookup_username: boolean; search: boolean; }`\n - `image_pack_import?: boolean`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst provisioningCapabilities = await client.bridges.retrieveCapabilities('local-whatsapp');\n\nconsole.log(provisioningCapabilities);\n```", perLanguage: { typescript: { method: 'client.bridges.retrieveCapabilities', @@ -468,14 +469,15 @@ const EMBEDDED_METHODS: MethodEntry[] = [ name: 'list', endpoint: '/v1/bridges/{bridgeID}/login-flows', httpMethod: 'get', - summary: 'List bridge login flows', - description: 'List bridge login flows that can be used to start a bridge login session.', + summary: 'List login flows', + description: + 'List connect and reconnect flow options for a bridge. Use a flowID when creating a bridge login session.', stainlessPath: '(resource) bridges.login_flows > (method) list', qualified: 'client.bridges.loginFlows.list', params: ['bridgeID: string;'], response: '{ items: { id: string; description?: string; name?: string; }[]; }', markdown: - "## list\n\n`client.bridges.loginFlows.list(bridgeID: string): { items: login_flow[]; }`\n\n**get** `/v1/bridges/{bridgeID}/login-flows`\n\nList bridge login flows that can be used to start a bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ items: { id: string; description?: string; name?: string; }[]; }`\n\n - `items: { id: string; description?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginFlows = await client.bridges.loginFlows.list('local-whatsapp');\n\nconsole.log(loginFlows);\n```", + "## list\n\n`client.bridges.loginFlows.list(bridgeID: string): { items: login_flow[]; }`\n\n**get** `/v1/bridges/{bridgeID}/login-flows`\n\nList connect and reconnect flow options for a bridge. Use a flowID when creating a bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ items: { id: string; description?: string; name?: string; }[]; }`\n\n - `items: { id: string; description?: string; name?: string; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginFlows = await client.bridges.loginFlows.list('local-whatsapp');\n\nconsole.log(loginFlows);\n```", perLanguage: { typescript: { method: 'client.bridges.loginFlows.list', @@ -508,155 +510,20 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, }, }, - { - name: 'list', - endpoint: '/v1/bridges/{bridgeID}/connections', - httpMethod: 'get', - summary: 'List bridge connections', - description: 'List durable bridge connection identities for a bridge.', - stainlessPath: '(resource) bridges.connections > (method) list', - qualified: 'client.bridges.connections.list', - params: ['bridgeID: string;'], - response: - "{ items: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }[]; }", - markdown: - "## list\n\n`client.bridges.connections.list(bridgeID: string): { items: bridge_connection[]; }`\n\n**get** `/v1/bridges/{bridgeID}/connections`\n\nList durable bridge connection identities for a bridge.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n### Returns\n\n- `{ items: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }[]; }`\n\n - `items: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst connections = await client.bridges.connections.list('local-whatsapp');\n\nconsole.log(connections);\n```", - perLanguage: { - typescript: { - method: 'client.bridges.connections.list', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst connections = await client.bridges.connections.list('local-whatsapp');\n\nconsole.log(connections.items);", - }, - python: { - method: 'bridges.connections.list', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nconnections = client.bridges.connections.list(\n "local-whatsapp",\n)\nprint(connections.items)', - }, - go: { - method: 'client.Bridges.Connections.List', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tconnections, err := client.Bridges.Connections.List(context.TODO(), "local-whatsapp")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", connections.Items)\n}\n', - }, - cli: { - method: 'connections list', - example: - "beeper-desktop bridges:connections list \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp", - }, - php: { - method: 'bridges->connections->list', - example: - "bridges->connections->list('local-whatsapp');\n\nvar_dump($connections);", - }, - http: { - example: - 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/connections \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'retrieve', - endpoint: '/v1/bridges/{bridgeID}/connections/{loginID}', - httpMethod: 'get', - summary: 'Get bridge connection', - description: 'Get one durable bridge connection identity.', - stainlessPath: '(resource) bridges.connections > (method) retrieve', - qualified: 'client.bridges.connections.retrieve', - params: ['bridgeID: string;', 'loginID: string;'], - response: - "{ bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }", - markdown: - "## retrieve\n\n`client.bridges.connections.retrieve(bridgeID: string, loginID: string): { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }`\n\n**get** `/v1/bridges/{bridgeID}/connections/{loginID}`\n\nGet one durable bridge connection identity.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginID: string`\n Bridge login ID.\n\n### Returns\n\n- `{ bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n Durable bridge connection identity. This is not guaranteed to be one-to-one with a Desktop API account.\n\n - `bridgeID: string`\n - `loginID: string`\n - `removeScopes: 'current-device' | 'all-devices'[]`\n - `status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'`\n - `accountIDs?: string[]`\n - `statusText?: string`\n - `user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst bridgeConnection = await client.bridges.connections.retrieve('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { bridgeID: 'local-whatsapp' });\n\nconsole.log(bridgeConnection);\n```", - perLanguage: { - typescript: { - method: 'client.bridges.connections.retrieve', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst bridgeConnection = await client.bridges.connections.retrieve(\n 'ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc',\n { bridgeID: 'local-whatsapp' },\n);\n\nconsole.log(bridgeConnection.bridgeID);", - }, - python: { - method: 'bridges.connections.retrieve', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nbridge_connection = client.bridges.connections.retrieve(\n login_id="ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc",\n bridge_id="local-whatsapp",\n)\nprint(bridge_connection.bridge_id)', - }, - go: { - method: 'client.Bridges.Connections.Get', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tbridgeConnection, err := client.Bridges.Connections.Get(\n\t\tcontext.TODO(),\n\t\t"ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc",\n\t\tbeeperdesktopapi.BridgeConnectionGetParams{\n\t\t\tBridgeID: "local-whatsapp",\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", bridgeConnection.BridgeID)\n}\n', - }, - cli: { - method: 'connections retrieve', - example: - "beeper-desktop bridges:connections retrieve \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp \\\n --login-id ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc", - }, - php: { - method: 'bridges->connections->retrieve', - example: - "bridges->connections->retrieve(\n 'ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', bridgeID: 'local-whatsapp'\n);\n\nvar_dump($bridgeConnection);", - }, - http: { - example: - 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/connections/$LOGIN_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'remove', - endpoint: '/v1/bridges/{bridgeID}/connections/{loginID}/remove', - httpMethod: 'post', - summary: 'Remove bridge connection', - description: 'Remove a bridge connection from this device or from all devices.', - stainlessPath: '(resource) bridges.connections > (method) remove', - qualified: 'client.bridges.connections.remove', - params: ['bridgeID: string;', 'loginID: string;', "scope: 'current-device' | 'all-devices';"], - response: - "{ bridgeID: string; loginID: string; scope: 'current-device' | 'all-devices'; status: 'removed'; affectedAccountIDs?: string[]; }", - markdown: - "## remove\n\n`client.bridges.connections.remove(bridgeID: string, loginID: string, scope: 'current-device' | 'all-devices'): { bridgeID: string; loginID: string; scope: 'current-device' | 'all-devices'; status: 'removed'; affectedAccountIDs?: string[]; }`\n\n**post** `/v1/bridges/{bridgeID}/connections/{loginID}/remove`\n\nRemove a bridge connection from this device or from all devices.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginID: string`\n Bridge login ID.\n\n- `scope: 'current-device' | 'all-devices'`\n Where this bridge connection should be removed.\n\n### Returns\n\n- `{ bridgeID: string; loginID: string; scope: 'current-device' | 'all-devices'; status: 'removed'; affectedAccountIDs?: string[]; }`\n\n - `bridgeID: string`\n - `loginID: string`\n - `scope: 'current-device' | 'all-devices'`\n - `status: 'removed'`\n - `affectedAccountIDs?: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst connection = await client.bridges.connections.remove('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { bridgeID: 'local-whatsapp', scope: 'current-device' });\n\nconsole.log(connection);\n```", - perLanguage: { - typescript: { - method: 'client.bridges.connections.remove', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst connection = await client.bridges.connections.remove('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', {\n bridgeID: 'local-whatsapp',\n scope: 'current-device',\n});\n\nconsole.log(connection.bridgeID);", - }, - python: { - method: 'bridges.connections.remove', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nconnection = client.bridges.connections.remove(\n login_id="ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc",\n bridge_id="local-whatsapp",\n scope="current-device",\n)\nprint(connection.bridge_id)', - }, - go: { - method: 'client.Bridges.Connections.Remove', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tconnection, err := client.Bridges.Connections.Remove(\n\t\tcontext.TODO(),\n\t\t"ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc",\n\t\tbeeperdesktopapi.BridgeConnectionRemoveParams{\n\t\t\tBridgeID: "local-whatsapp",\n\t\t\tScope: beeperdesktopapi.BridgeConnectionRemoveParamsScopeCurrentDevice,\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", connection.BridgeID)\n}\n', - }, - cli: { - method: 'connections remove', - example: - "beeper-desktop bridges:connections remove \\\n --access-token 'My Access Token' \\\n --bridge-id local-whatsapp \\\n --login-id ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc \\\n --scope current-device", - }, - php: { - method: 'bridges->connections->remove', - example: - "bridges->connections->remove(\n 'ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc',\n bridgeID: 'local-whatsapp',\n scope: 'current-device',\n);\n\nvar_dump($connection);", - }, - http: { - example: - 'curl http://localhost:23373/v1/bridges/$BRIDGE_ID/connections/$LOGIN_ID/remove \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "scope": "current-device"\n }\'', - }, - }, - }, { name: 'create', endpoint: '/v1/bridges/{bridgeID}/login-sessions', httpMethod: 'post', summary: 'Create bridge login session', description: - 'Start an add-account or reconnect flow for a bridge. Omit loginID/accountID to add a new account.', + 'Start a temporary bridge login session to connect a new chat account or reconnect an existing bridge login. Omit loginID and accountID to connect a new account.', stainlessPath: '(resource) bridges.login_sessions > (method) create', qualified: 'client.bridges.loginSessions.create', params: ['bridgeID: string;', 'accountID?: string;', 'flowID?: string;', 'loginID?: string;'], response: - "{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }", + "{ bridgeID: string; loginSessionID: string; status: string; account?: object; accountID?: string; currentStep?: { fields: login_input_field[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: cookie_field[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: object | object | object; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: account; instructions?: string; login?: object; stepID?: string; }; error?: object; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; loginID?: string; }", markdown: - "## create\n\n`client.bridges.loginSessions.create(bridgeID: string, accountID?: string, flowID?: string, loginID?: string): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; connection?: bridge_connection; currentStep?: object | object | object | object; error?: api_error; loginID?: string; }`\n\n**post** `/v1/bridges/{bridgeID}/login-sessions`\n\nStart an add-account or reconnect flow for a bridge. Omit loginID/accountID to add a new account.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `accountID?: string`\n\n- `flowID?: string`\n\n- `loginID?: string`\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; instructions?: string; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.create('local-whatsapp');\n\nconsole.log(loginSession);\n```", + "## create\n\n`client.bridges.loginSessions.create(bridgeID: string, accountID?: string, flowID?: string, loginID?: string): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; currentStep?: object | object | object | object; error?: api_error; login?: object; loginID?: string; }`\n\n**post** `/v1/bridges/{bridgeID}/login-sessions`\n\nStart a temporary bridge login session to connect a new chat account or reconnect an existing bridge login. Omit loginID and accountID to connect a new account.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `accountID?: string`\n Existing chat account ID to reconnect. Omit to connect a new account.\n\n- `flowID?: string`\n Optional flow ID returned by the list login flows endpoint. If omitted, Beeper chooses the default flow.\n\n- `loginID?: string`\n Existing bridge login ID to reconnect. Omit to connect a new account.\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; instructions?: string; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; stepID?: string; }; error?: { code: string; message: string; details?: object; }; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; instructions?: string; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.create('local-whatsapp');\n\nconsole.log(loginSession);\n```", perLanguage: { typescript: { method: 'client.bridges.loginSessions.create', @@ -681,7 +548,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ php: { method: 'bridges->loginSessions->create', example: - "bridges->loginSessions->create(\n 'local-whatsapp', accountID: 'accountID', flowID: 'flowID', loginID: 'loginID'\n);\n\nvar_dump($loginSession);", + "bridges->loginSessions->create(\n 'local-whatsapp', accountID: 'x', flowID: 'x', loginID: 'x'\n);\n\nvar_dump($loginSession);", }, http: { example: @@ -699,9 +566,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.bridges.loginSessions.retrieve', params: ['bridgeID: string;', 'loginSessionID: string;'], response: - "{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }", + "{ bridgeID: string; loginSessionID: string; status: string; account?: object; accountID?: string; currentStep?: { fields: login_input_field[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: cookie_field[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: object | object | object; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: account; instructions?: string; login?: object; stepID?: string; }; error?: object; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; loginID?: string; }", markdown: - "## retrieve\n\n`client.bridges.loginSessions.retrieve(bridgeID: string, loginSessionID: string): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; connection?: bridge_connection; currentStep?: object | object | object | object; error?: api_error; loginID?: string; }`\n\n**get** `/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}`\n\nGet the current state of a temporary bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginSessionID: string`\n Temporary bridge login session ID.\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; instructions?: string; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.retrieve('123', { bridgeID: 'local-whatsapp' });\n\nconsole.log(loginSession);\n```", + "## retrieve\n\n`client.bridges.loginSessions.retrieve(bridgeID: string, loginSessionID: string): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; currentStep?: object | object | object | object; error?: api_error; login?: object; loginID?: string; }`\n\n**get** `/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}`\n\nGet the current state of a temporary bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginSessionID: string`\n Temporary bridge login session ID.\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; instructions?: string; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; stepID?: string; }; error?: { code: string; message: string; details?: object; }; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; instructions?: string; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.retrieve('123', { bridgeID: 'local-whatsapp' });\n\nconsole.log(loginSession);\n```", perLanguage: { typescript: { method: 'client.bridges.loginSessions.retrieve', @@ -782,7 +649,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ name: 'submit', endpoint: '/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}/steps/{stepID}', httpMethod: 'post', - summary: 'Submit bridge login step', + summary: 'Submit login step', description: 'Submit input for the current step of a bridge login session.', stainlessPath: '(resource) bridges.login_sessions.steps > (method) submit', qualified: 'client.bridges.loginSessions.steps.submit', @@ -796,9 +663,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ "source?: 'api' | 'webview' | 'browser_extension';", ], response: - "{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }", + "{ bridgeID: string; loginSessionID: string; status: string; account?: object; accountID?: string; currentStep?: { fields: login_input_field[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: cookie_field[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: object | object | object; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: account; instructions?: string; login?: object; stepID?: string; }; error?: object; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; loginID?: string; }", markdown: - "## submit\n\n`client.bridges.loginSessions.steps.submit(bridgeID: string, loginSessionID: string, stepID: string, type: 'user_input' | 'cookies' | 'display_and_wait', fields?: object, lastURL?: string, source?: 'api' | 'webview' | 'browser_extension'): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; connection?: bridge_connection; currentStep?: object | object | object | object; error?: api_error; loginID?: string; }`\n\n**post** `/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}/steps/{stepID}`\n\nSubmit input for the current step of a bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginSessionID: string`\n Temporary bridge login session ID.\n\n- `stepID: string`\n Bridge login step ID.\n\n- `type: 'user_input' | 'cookies' | 'display_and_wait'`\n\n- `fields?: object`\n\n- `lastURL?: string`\n\n- `source?: 'api' | 'webview' | 'browser_extension'`\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; connection?: object; instructions?: string; stepID?: string; }; error?: { code: string; message: string; details?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; connection?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; instructions?: string; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.steps.submit('x', {\n bridgeID: 'local-whatsapp',\n loginSessionID: '123',\n type: 'user_input',\n});\n\nconsole.log(loginSession);\n```", + "## submit\n\n`client.bridges.loginSessions.steps.submit(bridgeID: string, loginSessionID: string, stepID: string, type: 'user_input' | 'cookies' | 'display_and_wait', fields?: object, lastURL?: string, source?: 'api' | 'webview' | 'browser_extension'): { bridgeID: string; loginSessionID: string; status: string; account?: account; accountID?: string; currentStep?: object | object | object | object; error?: api_error; login?: object; loginID?: string; }`\n\n**post** `/v1/bridges/{bridgeID}/login-sessions/{loginSessionID}/steps/{stepID}`\n\nSubmit input for the current step of a bridge login session.\n\n### Parameters\n\n- `bridgeID: string`\n Bridge ID.\n\n- `loginSessionID: string`\n Temporary bridge login session ID.\n\n- `stepID: string`\n Current bridge login session step ID.\n\n- `type: 'user_input' | 'cookies' | 'display_and_wait'`\n\n- `fields?: object`\n Field values keyed by the field IDs from the current step.\n\n- `lastURL?: string`\n Last browser URL reached during a cookies step, if available.\n\n- `source?: 'api' | 'webview' | 'browser_extension'`\n How the step was completed. Omit unless the client needs to distinguish an embedded webview or browser extension.\n\n### Returns\n\n- `{ bridgeID: string; loginSessionID: string; status: string; account?: { accountID: string; bridge: account_bridge; status: string; user: user; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; accountID?: string; currentStep?: { fields: object[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: object[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: object; instructions?: string; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: user; }; stepID?: string; }; error?: { code: string; message: string; details?: object; }; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: object; }; loginID?: string; }`\n\n - `bridgeID: string`\n - `loginSessionID: string`\n - `status: string`\n - `account?: { accountID: string; bridge: { id: string; provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; type: string; }; status: string; user: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; capabilities?: object; loginID?: string; network?: string; statusText?: string; }`\n - `accountID?: string`\n - `currentStep?: { fields: { id: string; initialValue?: string; label?: string; optional?: boolean; placeholder?: string; type?: string; }[]; stepID: string; type: 'user_input'; attachments?: object[]; instructions?: string; } | { fields: { id: string; name?: string; type?: 'cookie' | 'header' | 'local_storage'; }[]; stepID: string; type: 'cookies'; url: string; expectedFinalURLRegex?: string; extractJS?: string; instructions?: string; userAgent?: string; } | { display: { data: string; type: 'qr'; } | { imageURL: string; type: 'emoji'; } | { type: 'nothing'; }; stepID: string; type: 'display_and_wait'; instructions?: string; } | { type: 'complete'; account?: { accountID: string; bridge: object; status: string; user: object; capabilities?: object; loginID?: string; network?: string; statusText?: string; }; instructions?: string; login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }; stepID?: string; }`\n - `error?: { code: string; message: string; details?: object; }`\n - `login?: { bridgeID: string; loginID: string; removeScopes: 'current-device' | 'all-devices'[]; status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; accountIDs?: string[]; statusText?: string; user?: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }; }`\n - `loginID?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst loginSession = await client.bridges.loginSessions.steps.submit('x', {\n bridgeID: 'local-whatsapp',\n loginSessionID: '123',\n type: 'user_input',\n});\n\nconsole.log(loginSession);\n```", perLanguage: { typescript: { method: 'client.bridges.loginSessions.steps.submit', @@ -836,14 +703,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ endpoint: '/v1/chats/{chatID}', httpMethod: 'get', summary: 'Retrieve chat details', - description: 'Retrieve chat details including metadata, participants, and latest message', + description: 'Retrieve chat details, including metadata, participants, and the latest message.', stainlessPath: '(resource) chats > (method) retrieve', qualified: 'client.chats.retrieve', params: ['chatID: string;', 'maxParticipantCount?: number;'], response: "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## retrieve\n\n`client.chats.retrieve(chatID: string, maxParticipantCount?: number): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/{chatID}`\n\nRetrieve chat details including metadata, participants, and latest message\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `maxParticipantCount?: number`\n 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.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## retrieve\n\n`client.chats.retrieve(chatID: string, maxParticipantCount?: number): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/{chatID}`\n\nRetrieve chat details, including metadata, participants, and the latest message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `maxParticipantCount?: number`\n 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.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.retrieve('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { method: 'client.chats.retrieve', @@ -933,7 +800,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: '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+.', + 'Resolve a user/contact and open a direct chat. Reuses and returns an existing direct chat when one is found. Available in Beeper v4.2.808+.', stainlessPath: '(resource) chats > (method) start', qualified: 'client.chats.start', params: [ @@ -945,7 +812,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## start\n\n`client.chats.start(accountID: string, user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }, allowInvite?: boolean, messageText?: string): object`\n\n**post** `/v1/chats/start`\n\nResolve 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+.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }`\n Merged user-like contact payload used to resolve the best identifier.\n - `id?: string`\n Known user ID when available.\n - `email?: string`\n Email candidate.\n - `fullName?: string`\n Display name hint used for ranking only.\n - `phoneNumber?: string`\n Phone number candidate (E.164 preferred).\n - `username?: string`\n Username/handle candidate.\n\n- `allowInvite?: boolean`\n Whether invite-based DM creation is allowed when required by the platform.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);\n```", + "## start\n\n`client.chats.start(accountID: string, user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }, allowInvite?: boolean, messageText?: string): object`\n\n**post** `/v1/chats/start`\n\nResolve a user/contact and open a direct chat. Reuses and returns an existing direct chat when one is found. Available in Beeper v4.2.808+.\n\n### Parameters\n\n- `accountID: string`\n Account to create or start the chat on.\n\n- `user: { id?: string; email?: string; fullName?: string; phoneNumber?: string; username?: string; }`\n Contact-like user payload used to resolve the best identifier.\n - `id?: string`\n Known user ID when available.\n - `email?: string`\n Email candidate.\n - `fullName?: string`\n Display name hint used for ranking only.\n - `phoneNumber?: string`\n Phone number candidate (E.164 preferred).\n - `username?: string`\n Username/handle candidate.\n\n- `allowInvite?: boolean`\n Whether invite-based DM creation is allowed when required by the platform.\n\n- `messageText?: string`\n Optional first message content if the platform requires it to create the chat.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: user[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: object; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: object; participantActions?: object; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: object; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.start({\n accountID: 'accountID',\n user: {},\n});\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.chats.start', @@ -1048,7 +915,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## search\n\n`client.chats.search(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before', inbox?: 'primary' | 'low-priority' | 'archive', includeMuted?: boolean, lastActivityAfter?: string, lastActivityBefore?: string, limit?: number, query?: string, scope?: 'titles' | 'participants', type?: 'single' | 'group' | 'any', unreadOnly?: boolean): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/search`\n\nSearch chats by title, network, or participant names.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Provide an array of account IDs to filter chats from specific messaging accounts only\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `inbox?: 'primary' | 'low-priority' | 'archive'`\n Filter by inbox type: \"primary\" (non-archived, non-low-priority), \"low-priority\", or \"archive\". If not specified, shows all chats.\n\n- `includeMuted?: boolean`\n 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.\n\n- `lastActivityAfter?: string`\n Provide an ISO datetime string to only retrieve chats with last activity after this time\n\n- `lastActivityBefore?: string`\n Provide an ISO datetime string to only retrieve chats with last activity before this time\n\n- `limit?: number`\n Set the maximum number of chats to retrieve. Valid range: 1-200, default is 50\n\n- `query?: string`\n Literal token search (non-semantic). Use single words users type (e.g., \"dinner\"). When multiple words provided, ALL must match. Case-insensitive.\n\n- `scope?: 'titles' | 'participants'`\n Search scope: 'titles' matches title + network; 'participants' matches participant names.\n\n- `type?: 'single' | 'group' | 'any'`\n Specify the type of chats to retrieve: use \"single\" for direct messages, \"group\" for group chats, or \"any\" to get all types\n\n- `unreadOnly?: boolean`\n Set to true to only retrieve chats that have unread messages\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat);\n}\n```", + "## search\n\n`client.chats.search(accountIDs?: string[], cursor?: string, direction?: 'after' | 'before', inbox?: 'primary' | 'low-priority' | 'archive', includeMuted?: boolean, lastActivityAfter?: string, lastActivityBefore?: string, limit?: number, query?: string, scope?: 'titles' | 'participants', type?: 'single' | 'group' | 'any', unreadOnly?: boolean): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**get** `/v1/chats/search`\n\nSearch chats by title, network, or participant names.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit results to specific chat accounts.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `inbox?: 'primary' | 'low-priority' | 'archive'`\n Filter by inbox type: \"primary\" (non-archived, non-low-priority), \"low-priority\", or \"archive\". If not specified, shows all chats.\n\n- `includeMuted?: boolean`\n 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.\n\n- `lastActivityAfter?: string`\n Only include chats with last activity after this ISO 8601 datetime.\n\n- `lastActivityBefore?: string`\n Only include chats with last activity before this ISO 8601 datetime.\n\n- `limit?: number`\n Set the maximum number of chats to retrieve. Valid range: 1-200, default is 50\n\n- `query?: string`\n Literal chat search. Use words the user typed, such as \"dinner\". When multiple words are provided, all must match. Case-insensitive.\n\n- `scope?: 'titles' | 'participants'`\n Search scope: 'titles' matches title + network; 'participants' matches participant names.\n\n- `type?: 'single' | 'group' | 'any'`\n Specify the type of chats to retrieve: use \"single\" for direct messages, \"group\" for group chats, or \"any\" to get all types\n\n- `unreadOnly?: boolean`\n Set to true to only retrieve chats that have unread messages\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const chat of client.chats.search()) {\n console.log(chat);\n}\n```", perLanguage: { typescript: { method: 'client.chats.search', @@ -1086,12 +953,12 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: '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', + 'Archive or unarchive a chat. Set archived=true to move it to Archive, or archived=false to move it back to the inbox.', stainlessPath: '(resource) chats > (method) archive', qualified: 'client.chats.archive', params: ['chatID: string;', 'archived?: boolean;'], markdown: - "## archive\n\n`client.chats.archive(chatID: string, archived?: boolean): void`\n\n**post** `/v1/chats/{chatID}/archive`\n\nArchive or unarchive a chat. Set archived=true to move to archive, archived=false to move back to inbox\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `archived?: boolean`\n True to archive, false to unarchive\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", + "## archive\n\n`client.chats.archive(chatID: string, archived?: boolean): void`\n\n**post** `/v1/chats/{chatID}/archive`\n\nArchive or unarchive a chat. Set archived=true to move it to Archive, or archived=false to move it back to the inbox.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `archived?: boolean`\n True to archive, false to unarchive\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.archive('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", perLanguage: { typescript: { method: 'client.chats.archive', @@ -1130,7 +997,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: '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.', + 'Update supported chat fields. Non-empty drafts are accepted only when the current draft is empty. Send draft=null to clear the draft before setting new draft text or attachments.', stainlessPath: '(resource) chats > (method) update', qualified: 'client.chats.update', params: [ @@ -1148,7 +1015,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## update\n\n`client.chats.update(chatID: string, description?: string, draft?: { text: string; attachments?: object; }, imgURL?: string, isArchived?: boolean, isLowPriority?: boolean, isMuted?: boolean, isPinned?: boolean, messageExpirySeconds?: number, title?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**patch** `/v1/chats/{chatID}`\n\nUpdate 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.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `description?: string`\n Group chat description/topic. Support depends on the chat account and chat permissions.\n\n- `draft?: { text: string; attachments?: object; }`\n Draft object to set or clear. Non-empty drafts are only accepted when the current draft is empty. Send draft=null to clear text and attachments together before setting a new draft.\n - `text: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n - `attachments?: object`\n Draft attachments keyed by attachment ID. Each attachment must reference an uploadID returned by the upload file endpoint.\n\n- `imgURL?: string`\n Local filesystem path to a group chat avatar image. Support depends on the chat account and chat permissions.\n\n- `isArchived?: boolean`\n Archive or unarchive the chat.\n\n- `isLowPriority?: boolean`\n Mark or unmark the chat as low priority when supported by the account.\n\n- `isMuted?: boolean`\n Mute or unmute the chat.\n\n- `isPinned?: boolean`\n Pin or unpin the chat when supported by the account.\n\n- `messageExpirySeconds?: number`\n Disappearing-message timer in seconds, or null to clear when supported.\n\n- `title?: string`\n Custom chat title. Support depends on the chat account and chat permissions.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## update\n\n`client.chats.update(chatID: string, description?: string, draft?: { text: string; attachments?: object; }, imgURL?: string, isArchived?: boolean, isLowPriority?: boolean, isMuted?: boolean, isPinned?: boolean, messageExpirySeconds?: number, title?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**patch** `/v1/chats/{chatID}`\n\nUpdate supported chat fields. Non-empty drafts are accepted only when the current draft is empty. Send draft=null to clear the draft before setting new draft text or attachments.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `description?: string`\n Group chat description/topic. Support depends on the chat account and chat permissions.\n\n- `draft?: { text: string; attachments?: object; }`\n Draft object to set or clear. Non-empty drafts are only accepted when the current draft is empty. Send draft=null to clear text and attachments together before setting a new draft.\n - `text: string`\n Draft text. Plain text and Markdown are converted to Beeper rich text with the same rules used by send and edit.\n - `attachments?: object`\n Draft attachments keyed by attachment ID. Each attachment must reference an uploadID returned by the upload file endpoint.\n\n- `imgURL?: string`\n Local filesystem path to a group chat avatar image. Support depends on the chat account and chat permissions.\n\n- `isArchived?: boolean`\n Archive or unarchive the chat.\n\n- `isLowPriority?: boolean`\n Mark or unmark the chat as low priority when supported by the account.\n\n- `isMuted?: boolean`\n Mute or unmute the chat.\n\n- `isPinned?: boolean`\n Pin or unpin the chat when supported by the account.\n\n- `messageExpirySeconds?: number`\n Disappearing-message timer in seconds, or null to clear when supported.\n\n- `title?: string`\n Custom chat title. Support depends on the chat account and chat permissions.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.update('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { method: 'client.chats.update', @@ -1193,7 +1060,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## mark_read\n\n`client.chats.markRead(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/read`\n\nMark a chat as read, optionally through a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark read through.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## mark_read\n\n`client.chats.markRead(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/read`\n\nMark a chat as read, optionally through a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `messageID?: string`\n Optional message ID to mark read through.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markRead('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { method: 'client.chats.markRead', @@ -1238,7 +1105,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## mark_unread\n\n`client.chats.markUnread(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/unread`\n\nMark a chat as unread, optionally from a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID?: string`\n Optional message ID to mark unread from.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## mark_unread\n\n`client.chats.markUnread(chatID: string, messageID?: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/unread`\n\nMark a chat as unread, optionally from a specific message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `messageID?: string`\n Optional message ID to mark unread from.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.markUnread('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { method: 'client.chats.markUnread', @@ -1277,14 +1144,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: '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.', + 'Send a notification despite the recipient focus state when the network supports it. Currently intended for iMessage on macOS; unsupported networks return an error.', stainlessPath: '(resource) chats > (method) notify_anyway', qualified: 'client.chats.notifyAnyway', params: ['chatID: string;'], response: "{ id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }", markdown: - "## notify_anyway\n\n`client.chats.notifyAnyway(chatID: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/notify-anyway`\n\nForce a delivery notification when supported by the underlying network. Currently intended for iMessage on macOS; unsupported networks return an error.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", + "## notify_anyway\n\n`client.chats.notifyAnyway(chatID: string): { id: string; accountID: string; network: string; participants: object; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: object; description?: string; draft?: object; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: object; snooze?: object; unreadMentionsCount?: number; }`\n\n**post** `/v1/chats/{chatID}/notify-anyway`\n\nSend a notification despite the recipient focus state when the network supports it. Currently intended for iMessage on macOS; unsupported networks return an error.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n### Returns\n\n- `{ id: string; accountID: string; network: string; participants: { hasMore: boolean; items: object[]; total: number; }; title: string; type: 'single' | 'group'; unreadCount: number; capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: object; description?: object; disappearingTimer?: object; title?: object; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }; description?: string; draft?: { text: string; attachments?: object; }; imgURL?: string; isArchived?: boolean; isLowPriority?: boolean; isMarkedUnread?: boolean; isMuted?: boolean; isPinned?: boolean; isReadOnly?: boolean; lastActivity?: string; lastReadMessageSortKey?: string; localChatID?: string; messageExpirySeconds?: number; reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }; snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }; unreadMentionsCount?: number; }`\n\n - `id: string`\n - `accountID: string`\n - `network: string`\n - `participants: { hasMore: boolean; items: { id: string; cannotMessage?: boolean; email?: string; fullName?: string; imgURL?: string; isSelf?: boolean; phoneNumber?: string; username?: string; }[]; total: number; }`\n - `title: string`\n - `type: 'single' | 'group'`\n - `unreadCount: number`\n - `capabilities?: { allowedReactions?: string[]; archive?: boolean; attachments?: object; customEmojiReactions?: boolean; delete?: -2 | -1 | 0 | 1 | 2; deleteChat?: boolean; deleteChatForEveryone?: boolean; deleteForMe?: boolean; deleteMaxAge?: number; disappearingTimer?: { omitEmptyTimer?: boolean; timers?: number[]; types?: 'afterRead' | 'afterSend'[]; }; edit?: -2 | -1 | 0 | 1 | 2; editMaxAge?: number; editMaxCount?: number; formatting?: object; locationMessage?: -2 | -1 | 0 | 1 | 2; markAsUnread?: boolean; maxTextLength?: number; messageRequest?: { acceptWithButton?: -2 | -1 | 0 | 1 | 2; acceptWithMessage?: -2 | -1 | 0 | 1 | 2; }; participantActions?: { ban?: -2 | -1 | 0 | 1 | 2; invite?: -2 | -1 | 0 | 1 | 2; kick?: -2 | -1 | 0 | 1 | 2; leave?: -2 | -1 | 0 | 1 | 2; revokeInvite?: -2 | -1 | 0 | 1 | 2; }; poll?: -2 | -1 | 0 | 1 | 2; reaction?: -2 | -1 | 0 | 1 | 2; reactionCount?: number; readReceipts?: boolean; reply?: -2 | -1 | 0 | 1 | 2; state?: { avatar?: { level: -2 | -1 | 0 | 1 | 2; }; description?: { level: -2 | -1 | 0 | 1 | 2; }; disappearingTimer?: { level: -2 | -1 | 0 | 1 | 2; }; title?: { level: -2 | -1 | 0 | 1 | 2; }; }; thread?: -2 | -1 | 0 | 1 | 2; typingNotifications?: boolean; }`\n - `description?: string`\n - `draft?: { text: string; attachments?: object; }`\n - `imgURL?: string`\n - `isArchived?: boolean`\n - `isLowPriority?: boolean`\n - `isMarkedUnread?: boolean`\n - `isMuted?: boolean`\n - `isPinned?: boolean`\n - `isReadOnly?: boolean`\n - `lastActivity?: string`\n - `lastReadMessageSortKey?: string`\n - `localChatID?: string`\n - `messageExpirySeconds?: number`\n - `reminder?: { dismissOnIncomingMessage?: boolean; remindAt?: string; }`\n - `snooze?: { snoozeUntil?: string; userSnoozedAt?: string; }`\n - `unreadMentionsCount?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst chat = await client.chats.notifyAnyway('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(chat);\n```", perLanguage: { typescript: { method: 'client.chats.notifyAnyway', @@ -1322,12 +1189,12 @@ const EMBEDDED_METHODS: MethodEntry[] = [ endpoint: '/v1/chats/{chatID}/reminders', httpMethod: 'post', summary: 'Create a chat reminder', - description: 'Set a reminder for a chat at a specific time', + description: 'Set a reminder for a chat at a specific time.', stainlessPath: '(resource) chats.reminders > (method) create', qualified: 'client.chats.reminders.create', params: ['chatID: string;', 'reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; };'], markdown: - "## create\n\n`client.chats.reminders.create(chatID: string, reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }): void`\n\n**post** `/v1/chats/{chatID}/reminders`\n\nSet a reminder for a chat at a specific time\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }`\n Reminder configuration\n - `remindAt: string`\n Timestamp when the reminder should trigger.\n - `dismissOnIncomingMessage?: boolean`\n Cancel reminder if someone messages in the chat\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', { reminder: { remindAt: '2025-08-31T23:30:12.520Z' } })\n```", + "## create\n\n`client.chats.reminders.create(chatID: string, reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }): void`\n\n**post** `/v1/chats/{chatID}/reminders`\n\nSet a reminder for a chat at a specific time.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `reminder: { remindAt: string; dismissOnIncomingMessage?: boolean; }`\n Reminder configuration\n - `remindAt: string`\n Timestamp when the reminder should trigger.\n - `dismissOnIncomingMessage?: boolean`\n Cancel reminder if someone messages in the chat\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.create('!NCdzlIaMjZUmvmvyHU:beeper.com', { reminder: { remindAt: '2025-08-31T23:30:12.520Z' } })\n```", perLanguage: { typescript: { method: 'client.chats.reminders.create', @@ -1365,12 +1232,12 @@ const EMBEDDED_METHODS: MethodEntry[] = [ endpoint: '/v1/chats/{chatID}/reminders', httpMethod: 'delete', summary: 'Delete a chat reminder', - description: 'Clear an existing reminder from a chat', + description: 'Clear an existing reminder from a chat.', stainlessPath: '(resource) chats.reminders > (method) delete', qualified: 'client.chats.reminders.delete', params: ['chatID: string;'], markdown: - "## delete\n\n`client.chats.reminders.delete(chatID: string): void`\n\n**delete** `/v1/chats/{chatID}/reminders`\n\nClear an existing reminder from a chat\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", + "## delete\n\n`client.chats.reminders.delete(chatID: string): void`\n\n**delete** `/v1/chats/{chatID}/reminders`\n\nClear an existing reminder from a chat.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.chats.reminders.delete('!NCdzlIaMjZUmvmvyHU:beeper.com')\n```", perLanguage: { typescript: { method: 'client.chats.reminders.delete', @@ -1415,7 +1282,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: '{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }', markdown: - "## add\n\n`client.chats.messages.reactions.add(chatID: string, messageID: string, reactionKey: string, transactionID?: string): { chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n**post** `/v1/chats/{chatID}/messages/{messageID}/reactions`\n\nAdd a reaction to an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to add (emoji, shortcode, or custom emoji key)\n\n- `transactionID?: string`\n Optional transaction ID for deduplication and send tracking\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n - `transactionID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.messages.reactions.add('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', reactionKey: 'x' });\n\nconsole.log(response);\n```", + "## add\n\n`client.chats.messages.reactions.add(chatID: string, messageID: string, reactionKey: string, transactionID?: string): { chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n**post** `/v1/chats/{chatID}/messages/{messageID}/reactions`\n\nAdd a reaction to an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to add (emoji, shortcode, or custom emoji key)\n\n- `transactionID?: string`\n Optional transaction ID for deduplication and send tracking\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; transactionID: string; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n - `transactionID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.chats.messages.reactions.add('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', reactionKey: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.chats.messages.reactions.add', @@ -1459,7 +1326,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ params: ['chatID: string;', 'messageID: string;', 'reactionKey: string;'], response: '{ chatID: string; messageID: string; reactionKey: string; success: true; }', markdown: - "## delete\n\n`client.chats.messages.reactions.delete(chatID: string, messageID: string, reactionKey: string): { chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}`\n\nRemove the reaction added by the authenticated user from an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to remove (emoji, shortcode, or custom emoji key)\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reaction = await client.chats.messages.reactions.delete('x', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993' });\n\nconsole.log(reaction);\n```", + "## delete\n\n`client.chats.messages.reactions.delete(chatID: string, messageID: string, reactionKey: string): { chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}/reactions/{reactionKey}`\n\nRemove the reaction added by the authenticated user from an existing message.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `reactionKey: string`\n Reaction key to remove (emoji, shortcode, or custom emoji key)\n\n### Returns\n\n- `{ chatID: string; messageID: string; reactionKey: string; success: true; }`\n\n - `chatID: string`\n - `messageID: string`\n - `reactionKey: string`\n - `success: true`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reaction = await client.chats.messages.reactions.delete('x', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', messageID: '1343993' });\n\nconsole.log(reaction);\n```", perLanguage: { typescript: { method: 'client.chats.messages.reactions.delete', @@ -1518,7 +1385,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## search\n\n`client.messages.search(accountIDs?: string[], chatIDs?: string[], chatType?: 'group' | 'single', cursor?: string, dateAfter?: string, dateBefore?: string, direction?: 'after' | 'before', excludeLowPriority?: boolean, includeMuted?: boolean, limit?: number, mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[], query?: string, sender?: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/messages/search`\n\nSearch messages across chats.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit search to specific account IDs.\n\n- `chatIDs?: string[]`\n Limit search to specific chat IDs.\n\n- `chatType?: 'group' | 'single'`\n Filter by chat type: 'group' for group chats, 'single' for 1:1 chats.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `dateAfter?: string`\n Only include messages with timestamp strictly after this ISO 8601 datetime (e.g., '2024-07-01T00:00:00Z' or '2024-07-01T00:00:00+02:00').\n\n- `dateBefore?: string`\n Only include messages with timestamp strictly before this ISO 8601 datetime (e.g., '2024-07-31T23:59:59Z' or '2024-07-31T23:59:59+02:00').\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `excludeLowPriority?: boolean`\n Exclude messages marked Low Priority by the user. Default: true. Set to false to include all.\n\n- `includeMuted?: boolean`\n Include messages in 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.\n\n- `limit?: number`\n Maximum number of messages to return.\n\n- `mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[]`\n Filter messages by media types. Use ['any'] for any media type, or specify exact types like ['video', 'image']. Omit for no media filtering.\n\n- `query?: string`\n Literal word search (non-semantic). Finds messages containing these EXACT words in any order. Use single words users actually type, not concepts or phrases. Example: use \"dinner\" not \"dinner plans\", use \"sick\" not \"health issues\". If omitted, returns results filtered only by other parameters.\n\n- `sender?: string`\n Filter by sender: 'me' (messages sent by the authenticated user), 'others' (messages sent by others), or a specific user ID string (user.id).\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message);\n}\n```", + "## search\n\n`client.messages.search(accountIDs?: string[], chatIDs?: string[], chatType?: 'group' | 'single', cursor?: string, dateAfter?: string, dateBefore?: string, direction?: 'after' | 'before', excludeLowPriority?: boolean, includeMuted?: boolean, limit?: number, mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[], query?: string, sender?: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/messages/search`\n\nSearch messages across chats.\n\n### Parameters\n\n- `accountIDs?: string[]`\n Limit search to specific account IDs.\n\n- `chatIDs?: string[]`\n Limit search to specific chat IDs.\n\n- `chatType?: 'group' | 'single'`\n Filter by chat type: 'group' for group chats, 'single' for 1:1 chats.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `dateAfter?: string`\n Only include messages with timestamp strictly after this ISO 8601 datetime (e.g., '2024-07-01T00:00:00Z' or '2024-07-01T00:00:00+02:00').\n\n- `dateBefore?: string`\n Only include messages with timestamp strictly before this ISO 8601 datetime (e.g., '2024-07-31T23:59:59Z' or '2024-07-31T23:59:59+02:00').\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n- `excludeLowPriority?: boolean`\n Exclude messages marked Low Priority by the user. Default: true. Set to false to include all.\n\n- `includeMuted?: boolean`\n Include messages in 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.\n\n- `limit?: number`\n Maximum number of messages to return.\n\n- `mediaTypes?: 'any' | 'video' | 'image' | 'link' | 'file'[]`\n Filter messages by media types. Use ['any'] for any media type, or specify exact types like ['video', 'image']. Omit for no media filtering.\n\n- `query?: string`\n Literal word search. Finds messages containing these words in any order. Use words the user actually typed, not inferred concepts. Example: use \"dinner\" rather than \"dinner plans\". If omitted, returns results filtered only by the other parameters.\n\n- `sender?: string`\n Filter by sender: 'me' (messages sent by the authenticated user), 'others' (messages sent by others), or a specific user ID string (user.id).\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.search()) {\n console.log(message);\n}\n```", perLanguage: { typescript: { method: 'client.messages.search', @@ -1562,7 +1429,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## list\n\n`client.messages.list(chatID: string, cursor?: string, direction?: 'after' | 'before'): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages`\n\nList all messages in a chat with cursor-based pagination. Sorted by timestamp.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message);\n}\n```", + "## list\n\n`client.messages.list(chatID: string, cursor?: string, direction?: 'after' | 'before'): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages`\n\nList all messages in a chat with cursor-based pagination. Sorted by timestamp.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `cursor?: string`\n Opaque pagination cursor; do not inspect. Use together with 'direction'.\n\n- `direction?: 'after' | 'before'`\n Pagination direction used with 'cursor': 'before' fetches older results, 'after' fetches newer results. Defaults to 'before' when only 'cursor' is provided.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\n// Automatically fetches more pages as needed.\nfor await (const message of client.messages.list('!NCdzlIaMjZUmvmvyHU:beeper.com')) {\n console.log(message);\n}\n```", perLanguage: { typescript: { method: 'client.messages.list', @@ -1612,7 +1479,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ ], response: '{ chatID: string; pendingMessageID: string; }', markdown: - "## send\n\n`client.messages.send(chatID: string, attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }, replyToMessageID?: string, text?: string): { chatID: string; pendingMessageID: string; }`\n\n**post** `/v1/chats/{chatID}/messages`\n\nSend a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }`\n Single attachment to send with the message\n - `uploadID: string`\n Upload ID from uploadAsset endpoint. Required to reference uploaded files.\n - `duration?: number`\n Duration in seconds (optional override of cached value)\n - `fileName?: string`\n Filename (optional override of cached value)\n - `mimeType?: string`\n MIME type (optional override of cached value)\n - `size?: { height: number; width: number; }`\n Dimensions (optional override of cached value)\n - `type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'`\n Attachment type hint (image, video, audio, file, gif, voice-note, sticker). If omitted, auto-detected from mimeType\n\n- `replyToMessageID?: string`\n Provide a message ID to send this as a reply to an existing message\n\n- `text?: string`\n Draft text. Plain text and Markdown are converted to Matrix HTML with the same rules used by send and edit.\n\n### Returns\n\n- `{ chatID: string; pendingMessageID: string; }`\n\n - `chatID: string`\n - `pendingMessageID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response);\n```", + "## send\n\n`client.messages.send(chatID: string, attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }, replyToMessageID?: string, text?: string): { chatID: string; pendingMessageID: string; }`\n\n**post** `/v1/chats/{chatID}/messages`\n\nSend a text message to a specific chat. Supports replying to existing messages. Returns a pending message ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `attachment?: { uploadID: string; duration?: number; fileName?: string; mimeType?: string; size?: { height: number; width: number; }; type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'; }`\n Single attachment to send with the message\n - `uploadID: string`\n Upload ID from uploadAsset endpoint. Required to reference uploaded files.\n - `duration?: number`\n Duration in seconds (optional override of cached value)\n - `fileName?: string`\n Filename (optional override of cached value)\n - `mimeType?: string`\n MIME type (optional override of cached value)\n - `size?: { height: number; width: number; }`\n Dimensions (optional override of cached value)\n - `type?: 'image' | 'video' | 'audio' | 'file' | 'gif' | 'voice-note' | 'sticker'`\n Attachment type hint (image, video, audio, file, gif, voice-note, sticker). If omitted, auto-detected from mimeType\n\n- `replyToMessageID?: string`\n Provide a message ID to send this as a reply to an existing message\n\n- `text?: string`\n Draft text. Plain text and Markdown are converted to Beeper rich text with the same rules used by send and edit.\n\n### Returns\n\n- `{ chatID: string; pendingMessageID: string; }`\n\n - `chatID: string`\n - `pendingMessageID: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.messages.send('!NCdzlIaMjZUmvmvyHU:beeper.com');\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.messages.send', @@ -1651,14 +1518,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: 'get', summary: 'Retrieve a message', description: - 'Retrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.', + 'Retrieve a message by final message ID, pendingMessageID, or Matrix event ID. chatID may be a Beeper chat ID or a local chat ID.', stainlessPath: '(resource) messages > (method) retrieve', qualified: 'client.messages.retrieve', params: ['chatID: string;', 'messageID: string;'], response: "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## retrieve\n\n`client.messages.retrieve(chatID: string, messageID: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages/{messageID}`\n\nRetrieve a message by final message ID, pendingMessageID, or Matrix event ID. Chat ID may be a Beeper chat ID or local chat ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.retrieve('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });\n\nconsole.log(message);\n```", + "## retrieve\n\n`client.messages.retrieve(chatID: string, messageID: string): { id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: attachment[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: object[]; mentions?: string[]; reactions?: reaction[]; seen?: boolean | string | object; senderName?: string; sendStatus?: object; text?: string; type?: string; }`\n\n**get** `/v1/chats/{chatID}/messages/{messageID}`\n\nRetrieve a message by final message ID, pendingMessageID, or Matrix event ID. chatID may be a Beeper chat ID or a local chat ID.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `messageID: string`\n Message ID.\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: object; srcURL?: string; transcription?: object; }[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n - `id: string`\n - `accountID: string`\n - `chatID: string`\n - `senderID: string`\n - `sortKey: string`\n - `timestamp: string`\n - `attachments?: { type: 'unknown' | 'img' | 'video' | 'audio'; id?: string; duration?: number; fileName?: string; fileSize?: number; isGif?: boolean; isSticker?: boolean; isVoiceNote?: boolean; mimeType?: string; posterImg?: string; size?: { height?: number; width?: number; }; srcURL?: string; transcription?: { engine: string; transcription: string; language?: string; }; }[]`\n - `editedTimestamp?: string`\n - `isDeleted?: boolean`\n - `isHidden?: boolean`\n - `isSender?: boolean`\n - `isUnread?: boolean`\n - `linkedMessageID?: string`\n - `links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: { height?: number; width?: number; }; originalURL?: string; summary?: string; }[]`\n - `mentions?: string[]`\n - `reactions?: { id: string; participantID: string; reactionKey: string; emoji?: boolean; imgURL?: string; }[]`\n - `seen?: boolean | string | object`\n - `senderName?: string`\n - `sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }`\n - `text?: string`\n - `type?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.retrieve('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' });\n\nconsole.log(message);\n```", perLanguage: { typescript: { method: 'client.messages.retrieve', @@ -1703,7 +1570,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }", markdown: - "## update\n\n`client.messages.update(chatID: string, messageID: string, text: string): object`\n\n**put** `/v1/chats/{chatID}/messages/{messageID}`\n\nEdit the text content of an existing message. Messages with attachments cannot be edited.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `text: string`\n New text content for the message\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.update('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x' });\n\nconsole.log(message);\n```", + "## update\n\n`client.messages.update(chatID: string, messageID: string, text: string): object`\n\n**put** `/v1/chats/{chatID}/messages/{messageID}`\n\nEdit the text content of an existing message. Messages with attachments cannot be edited.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `text: string`\n New text content for the message\n\n### Returns\n\n- `{ id: string; accountID: string; chatID: string; senderID: string; sortKey: string; timestamp: string; attachments?: object[]; editedTimestamp?: string; isDeleted?: boolean; isHidden?: boolean; isSender?: boolean; isUnread?: boolean; linkedMessageID?: string; links?: { title: string; url: string; favicon?: string; img?: string; imgSize?: object; originalURL?: string; summary?: string; }[]; mentions?: string[]; reactions?: object[]; seen?: boolean | string | object; senderName?: string; sendStatus?: { status: 'SUCCESS' | 'PENDING' | 'FAIL_RETRIABLE' | 'FAIL_PERMANENT'; timestamp: string; deliveredToUsers?: string[]; internalError?: string; message?: string; reason?: string; }; text?: string; type?: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst message = await client.messages.update('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com', text: 'x' });\n\nconsole.log(message);\n```", perLanguage: { typescript: { method: 'client.messages.update', @@ -1747,7 +1614,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.messages.delete', params: ['chatID: string;', 'messageID: string;', 'forEveryone?: boolean;'], markdown: - "## delete\n\n`client.messages.delete(chatID: string, messageID: string, forEveryone?: boolean): void`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}`\n\nDelete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this Beeper Desktop installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `forEveryone?: boolean`\n True to request deletion for everyone when the network supports it; false to delete only for the authenticated user when supported.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' })\n```", + "## delete\n\n`client.messages.delete(chatID: string, messageID: string, forEveryone?: boolean): void`\n\n**delete** `/v1/chats/{chatID}/messages/{messageID}`\n\nDelete a message by final message ID. Pending message IDs are not accepted because messages cannot be deleted while sending.\n\n### Parameters\n\n- `chatID: string`\n Chat ID. Input routes also accept the local chat ID from this installation when available.\n\n- `messageID: string`\n Message ID.\n\n- `forEveryone?: boolean`\n True to request deletion for everyone when the network supports it; false to delete only for the authenticated user when supported.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.messages.delete('1343993', { chatID: '!NCdzlIaMjZUmvmvyHU:beeper.com' })\n```", perLanguage: { typescript: { method: 'client.messages.delete', @@ -1786,13 +1653,13 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: '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.', + 'Download a file from an mxc:// or localmxc:// URL to the device running the Beeper Client API and return the local file URL.', stainlessPath: '(resource) assets > (method) download', qualified: 'client.assets.download', params: ['url: string;'], response: '{ error?: string; srcURL?: string; }', markdown: - "## download\n\n`client.assets.download(url: string): { error?: string; srcURL?: string; }`\n\n**post** `/v1/assets/download`\n\nDownload a Matrix file using its mxc:// or localmxc:// URL to the device running Beeper Desktop and return the local file URL.\n\n### Parameters\n\n- `url: string`\n Matrix content URL (mxc:// or localmxc://) for the file to download.\n\n### Returns\n\n- `{ error?: string; srcURL?: string; }`\n\n - `error?: string`\n - `srcURL?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response);\n```", + "## download\n\n`client.assets.download(url: string): { error?: string; srcURL?: string; }`\n\n**post** `/v1/assets/download`\n\nDownload a file from an mxc:// or localmxc:// URL to the device running the Beeper Client API and return the local file URL.\n\n### Parameters\n\n- `url: string`\n Beeper media URL (mxc:// or localmxc://) for the file to download.\n\n### Returns\n\n- `{ error?: string; srcURL?: string; }`\n\n - `error?: string`\n - `srcURL?: string`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.download({ url: 'mxc://example.org/Q4x9CqGz1pB3Oa6XgJ' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.assets.download', @@ -1831,14 +1698,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: '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.', + 'Upload a file to a temporary location using multipart/form-data. Returns an uploadID that can be referenced when sending a message or creating a draft attachment.', stainlessPath: '(resource) assets > (method) upload', qualified: 'client.assets.upload', params: ['file: string;', 'fileName?: string;', 'mimeType?: string;'], response: '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', markdown: - "## upload\n\n`client.assets.upload(file: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload`\n\nUpload 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.\n\n### Parameters\n\n- `file: string`\n The file to upload (max 500 MB).\n\n- `fileName?: string`\n Original filename. Defaults to the uploaded file name if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response);\n```", + "## upload\n\n`client.assets.upload(file: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload`\n\nUpload a file to a temporary location using multipart/form-data. Returns an uploadID that can be referenced when sending a message or creating a draft attachment.\n\n### Parameters\n\n- `file: string`\n The file to upload (max 500 MB).\n\n- `fileName?: string`\n Original filename. Defaults to the uploaded file name if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.upload({ file: fs.createReadStream('path/to/file') });\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.assets.upload', @@ -1877,14 +1744,14 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: '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.', + 'Upload a file using a JSON body with base64-encoded content. Returns an uploadID that can be referenced when sending a message or creating a draft attachment. Alternative to the multipart upload endpoint.', stainlessPath: '(resource) assets > (method) upload_base64', qualified: 'client.assets.uploadBase64', params: ['content: string;', 'fileName?: string;', 'mimeType?: string;'], response: '{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }', markdown: - "## upload_base64\n\n`client.assets.uploadBase64(content: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload/base64`\n\nUpload 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.\n\n### Parameters\n\n- `content: string`\n Base64-encoded file content (max ~500MB decoded)\n\n- `fileName?: string`\n Original filename. Generated if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response);\n```", + "## upload_base64\n\n`client.assets.uploadBase64(content: string, fileName?: string, mimeType?: string): { duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n**post** `/v1/assets/upload/base64`\n\nUpload a file using a JSON body with base64-encoded content. Returns an uploadID that can be referenced when sending a message or creating a draft attachment. Alternative to the multipart upload endpoint.\n\n### Parameters\n\n- `content: string`\n Base64-encoded file content (max ~500MB decoded)\n\n- `fileName?: string`\n Original filename. Generated if omitted\n\n- `mimeType?: string`\n MIME type. Auto-detected from magic bytes if omitted\n\n### Returns\n\n- `{ duration?: number; error?: string; fileName?: string; fileSize?: number; height?: number; mimeType?: string; srcURL?: string; uploadID?: string; width?: number; }`\n\n - `duration?: number`\n - `error?: string`\n - `fileName?: string`\n - `fileSize?: number`\n - `height?: number`\n - `mimeType?: string`\n - `srcURL?: string`\n - `uploadID?: string`\n - `width?: number`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.assets.uploadBase64({ content: 'x' });\n\nconsole.log(response);\n```", perLanguage: { typescript: { method: 'client.assets.uploadBase64', @@ -1967,13 +1834,13 @@ const EMBEDDED_METHODS: MethodEntry[] = [ httpMethod: 'get', summary: 'Retrieve server info', description: - 'Returns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.', + 'Returns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Client API server.', stainlessPath: '(resource) info > (method) retrieve', qualified: 'client.info.retrieve', response: '{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }', markdown: - "## retrieve\n\n`client.info.retrieve(): { app: object; endpoints: object; platform: object; server: object; }`\n\n**get** `/v1/info`\n\nReturns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Desktop instance.\n\n### Returns\n\n- `{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }`\n\n - `app: { bundle_id: string; name: string; version: string; }`\n - `endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }`\n - `platform: { arch: string; os: string; release?: string; }`\n - `server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info);\n```", + "## retrieve\n\n`client.info.retrieve(): { app: object; endpoints: object; platform: object; server: object; }`\n\n**get** `/v1/info`\n\nReturns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata for this Beeper Client API server.\n\n### Returns\n\n- `{ app: { bundle_id: string; name: string; version: string; }; endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }; platform: { arch: string; os: string; release?: string; }; server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }; }`\n\n - `app: { bundle_id: string; name: string; version: string; }`\n - `endpoints: { mcp: string; oauth: { authorization_endpoint: string; introspection_endpoint: string; registration_endpoint: string; revocation_endpoint: string; token_endpoint: string; userinfo_endpoint: string; }; spec: string; ws_events: string; }`\n - `platform: { arch: string; os: string; release?: string; }`\n - `server: { base_url: string; hostname: string; mcp_enabled: boolean; port: number; remote_access: boolean; status: string; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst info = await client.info.retrieve();\n\nconsole.log(info);\n```", perLanguage: { typescript: { method: 'client.info.retrieve', @@ -2005,765 +1872,6 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, }, }, - { - name: 'session', - endpoint: '/v1/app/session', - httpMethod: 'get', - summary: 'Get app session', - description: - 'Return the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.', - stainlessPath: '(resource) app > (method) session', - qualified: 'client.app.session', - response: - "{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }", - markdown: - "## session\n\n`client.app.session(): { e2ee: object; state: string; matrix?: object; verification?: object; }`\n\n**get** `/v1/app/session`\n\nReturn the current Beeper Desktop sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that login is needed; after sign-in, pass a read token.\n\n### Returns\n\n- `{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }`\n - `state: string`\n - `matrix?: { deviceID: string; homeserver: string; userID: string; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.session();\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.session', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.session();\n\nconsole.log(response.e2ee);", - }, - python: { - method: 'app.session', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.session()\nprint(response.e2ee)', - }, - go: { - method: 'client.App.Session', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Session(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.E2EE)\n}\n', - }, - cli: { - method: 'app session', - example: "beeper-desktop app session \\\n --access-token 'My Access Token'", - }, - php: { - method: 'app->session', - example: - "app->session();\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/session \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'start', - endpoint: '/v1/app/login/start', - httpMethod: 'post', - summary: 'Start app login', - description: 'Start a first-party Beeper Desktop sign-in session.', - stainlessPath: '(resource) app.login > (method) start', - qualified: 'client.app.login.start', - response: '{ request: string; type: string[]; }', - markdown: - "## start\n\n`client.app.login.start(): { request: string; type: string[]; }`\n\n**post** `/v1/app/login/start`\n\nStart a first-party Beeper Desktop sign-in session.\n\n### Returns\n\n- `{ request: string; type: string[]; }`\n\n - `request: string`\n - `type: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.login.start', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response.request);", - }, - python: { - method: 'app.login.start', - example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.start()\nprint(response.request)', - }, - go: { - method: 'client.App.Login.Start', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Start(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Request)\n}\n', - }, - cli: { - method: 'login start', - example: "beeper-desktop app:login start \\\n --access-token 'My Access Token'", - }, - php: { - method: 'app->login->start', - example: - "app->login->start();\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/login/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'email', - endpoint: '/v1/app/login/email', - httpMethod: 'post', - summary: 'Send login code', - description: 'Send a sign-in code to the user email address.', - stainlessPath: '(resource) app.login > (method) email', - qualified: 'client.app.login.email', - params: ['email: string;', 'request: string;'], - response: 'object', - markdown: - "## email\n\n`client.app.login.email(email: string, request: string): object`\n\n**post** `/v1/app/login/email`\n\nSend a sign-in code to the user email address.\n\n### Parameters\n\n- `email: string`\n Email address to send the sign-in code to.\n\n- `request: string`\n Login request ID returned by the start step.\n\n### Returns\n\n- `object`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.login.email', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' });\n\nconsole.log(response);", - }, - python: { - method: 'app.login.email', - example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.email(\n email="dev@stainless.com",\n request="request",\n)\nprint(response)', - }, - go: { - method: 'client.App.Login.Email', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Email(context.TODO(), beeperdesktopapi.AppLoginEmailParams{\n\t\tEmail: "dev@stainless.com",\n\t\tRequest: "request",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', - }, - cli: { - method: 'login email', - example: - "beeper-desktop app:login email \\\n --access-token 'My Access Token' \\\n --email dev@stainless.com \\\n --request request", - }, - php: { - method: 'app->login->email', - example: - "app->login->email(\n email: 'dev@stainless.com', request: 'request'\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/login/email \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "email": "dev@stainless.com",\n "request": "request"\n }\'', - }, - }, - }, - { - name: 'response', - endpoint: '/v1/app/login/response', - httpMethod: 'post', - summary: 'Complete login with code', - description: - 'Finish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.', - stainlessPath: '(resource) app.login > (method) response', - qualified: 'client.app.login.response', - params: ['request: string;', 'response: string;'], - response: - "{ desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }", - markdown: - "## response\n\n`client.app.login.response(request: string, response: string): { desktopAPI: object; matrix: object; session: object; } | { copy: object; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n**post** `/v1/app/login/response`\n\nFinish sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.\n\n### Parameters\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `response: string`\n Sign-in code from the user email.\n\n### Returns\n\n- `{ desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; request: string; usernameSuggestions?: string[]; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.login.response', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ request: 'request', response: 'response' });\n\nconsole.log(response);", - }, - python: { - method: 'app.login.response', - example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.response(\n request="request",\n response="response",\n)\nprint(response)', - }, - go: { - method: 'client.App.Login.Response', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Response(context.TODO(), beeperdesktopapi.AppLoginResponseParams{\n\t\tRequest: "request",\n\t\tResponse: "response",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', - }, - cli: { - method: 'login response', - example: - "beeper-desktop app:login response \\\n --access-token 'My Access Token' \\\n --request request \\\n --response response", - }, - php: { - method: 'app->login->response', - example: - "app->login->response(\n request: 'request', response: 'response'\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/login/response \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "request": "request",\n "response": "response"\n }\'', - }, - }, - }, - { - name: 'register', - endpoint: '/v1/app/login/register', - httpMethod: 'post', - summary: 'Create account', - description: 'Create a Beeper account after the user chooses a username and accepts the Terms of Use.', - stainlessPath: '(resource) app.login > (method) register', - qualified: 'client.app.login.register', - params: ['acceptTerms: true;', 'leadToken: string;', 'request: string;', 'username: string;'], - response: - "{ desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", - markdown: - "## register\n\n`client.app.login.register(acceptTerms: true, leadToken: string, request: string, username: string): { desktopAPI: object; matrix: object; session: object; }`\n\n**post** `/v1/app/login/register`\n\nCreate a Beeper account after the user chooses a username and accepts the Terms of Use.\n\n### Parameters\n\n- `acceptTerms: true`\n Confirms that the user accepted the Terms of Use and acknowledged the Privacy Policy.\n\n- `leadToken: string`\n Registration token returned by Beeper.\n\n- `request: string`\n Login request ID returned by the start step.\n\n- `username: string`\n Username selected by the user.\n\n### Returns\n\n- `{ desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }; matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `desktopAPI: { accessToken: string; scope: 'read write'; tokenType: 'Bearer'; }`\n - `matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }`\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.login.register', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n request: 'request',\n username: 'x',\n});\n\nconsole.log(response.desktopAPI);", - }, - python: { - method: 'app.login.register', - example: - 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.register(\n accept_terms=True,\n lead_token="leadToken",\n request="request",\n username="x",\n)\nprint(response.desktop_api)', - }, - go: { - method: 'client.App.Login.Register', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Register(context.TODO(), beeperdesktopapi.AppLoginRegisterParams{\n\t\tAcceptTerms: true,\n\t\tLeadToken: "leadToken",\n\t\tRequest: "request",\n\t\tUsername: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.DesktopAPI)\n}\n', - }, - cli: { - method: 'login register', - example: - "beeper-desktop app:login register \\\n --access-token 'My Access Token' \\\n --accept-terms true \\\n --lead-token leadToken \\\n --request request \\\n --username x", - }, - php: { - method: 'app->login->register', - example: - "app->login->register(\n acceptTerms: true, leadToken: 'leadToken', request: 'request', username: 'x'\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/login/register \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "acceptTerms": true,\n "leadToken": "leadToken",\n "request": "request",\n "username": "x"\n }\'', - }, - }, - }, - { - name: 'verify', - endpoint: '/v1/app/login/verification/recovery-key', - httpMethod: 'post', - summary: 'Verify with recovery key', - description: 'Unlock encrypted messages with the user recovery key.', - stainlessPath: '(resource) app.login.verification.recovery_key > (method) verify', - qualified: 'client.app.login.verification.recoveryKey.verify', - params: ['recoveryKey: string;'], - response: - "{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", - markdown: - "## verify\n\n`client.app.login.verification.recoveryKey.verify(recoveryKey: string): { session: object; }`\n\n**post** `/v1/app/login/verification/recovery-key`\n\nUnlock encrypted messages with the user recovery key.\n\n### Parameters\n\n- `recoveryKey: string`\n Recovery key saved by the user.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.login.verification.recoveryKey.verify', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' });\n\nconsole.log(response.session);", - }, - python: { - method: 'app.login.verification.recovery_key.verify', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.login.verification.recovery_key.verify(\n recovery_key="x",\n)\nprint(response.session)', - }, - go: { - method: 'client.App.Login.Verification.RecoveryKey.Verify', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Verification.RecoveryKey.Verify(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyVerifyParams{\n\t\tRecoveryKey: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', - }, - cli: { - method: 'recovery_key verify', - example: - "beeper-desktop app:login:verification:recovery-key verify \\\n --access-token 'My Access Token' \\\n --recovery-key x", - }, - php: { - method: 'app->login->verification->recoveryKey->verify', - example: - "app->login->verification->recoveryKey->verify(\n recoveryKey: 'x'\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/login/verification/recovery-key \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryKey": "x"\n }\'', - }, - }, - }, - { - name: 'create', - endpoint: '/v1/app/login/verification/recovery-key/reset', - httpMethod: 'post', - summary: 'Create new recovery key', - description: 'Create a new recovery key when the user cannot use the existing one.', - stainlessPath: '(resource) app.login.verification.recovery_key.reset > (method) create', - qualified: 'client.app.login.verification.recoveryKey.reset.create', - params: ['existingRecoveryKey?: string;'], - response: - "{ recoveryKey: string; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", - markdown: - "## create\n\n`client.app.login.verification.recoveryKey.reset.create(existingRecoveryKey?: string): { recoveryKey: string; session: object; }`\n\n**post** `/v1/app/login/verification/recovery-key/reset`\n\nCreate a new recovery key when the user cannot use the existing one.\n\n### Parameters\n\n- `existingRecoveryKey?: string`\n Existing recovery key, if the user has it.\n\n### Returns\n\n- `{ recoveryKey: string; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `recoveryKey: string`\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reset = await client.app.login.verification.recoveryKey.reset.create();\n\nconsole.log(reset);\n```", - perLanguage: { - typescript: { - method: 'client.app.login.verification.recoveryKey.reset.create', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reset = await client.app.login.verification.recoveryKey.reset.create();\n\nconsole.log(reset.recoveryKey);", - }, - python: { - method: 'app.login.verification.recovery_key.reset.create', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreset = client.app.login.verification.recovery_key.reset.create()\nprint(reset.recovery_key)', - }, - go: { - method: 'client.App.Login.Verification.RecoveryKey.Reset.New', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treset, err := client.App.Login.Verification.RecoveryKey.Reset.New(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyResetNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reset.RecoveryKey)\n}\n', - }, - cli: { - method: 'reset create', - example: - "beeper-desktop app:login:verification:recovery-key:reset create \\\n --access-token 'My Access Token'", - }, - php: { - method: 'app->login->verification->recoveryKey->reset->create', - example: - "app->login->verification->recoveryKey->reset->create(\n existingRecoveryKey: 'existingRecoveryKey'\n);\n\nvar_dump($reset);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/login/verification/recovery-key/reset \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'confirm', - endpoint: '/v1/app/login/verification/recovery-key/reset/confirm', - httpMethod: 'post', - summary: 'Confirm new recovery key', - description: 'Confirm that the new recovery key should be used for this account.', - stainlessPath: '(resource) app.login.verification.recovery_key.reset > (method) confirm', - qualified: 'client.app.login.verification.recoveryKey.reset.confirm', - params: ['recoveryKey: string;'], - response: - "{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", - markdown: - "## confirm\n\n`client.app.login.verification.recoveryKey.reset.confirm(recoveryKey: string): { session: object; }`\n\n**post** `/v1/app/login/verification/recovery-key/reset/confirm`\n\nConfirm that the new recovery key should be used for this account.\n\n### Parameters\n\n- `recoveryKey: string`\n New recovery key returned by the reset step.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.login.verification.recoveryKey.reset.confirm', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.login.verification.recoveryKey.reset.confirm({\n recoveryKey: 'x',\n});\n\nconsole.log(response.session);", - }, - python: { - method: 'app.login.verification.recovery_key.reset.confirm', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.login.verification.recovery_key.reset.confirm(\n recovery_key="x",\n)\nprint(response.session)', - }, - go: { - method: 'client.App.Login.Verification.RecoveryKey.Reset.Confirm', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Verification.RecoveryKey.Reset.Confirm(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyResetConfirmParams{\n\t\tRecoveryKey: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', - }, - cli: { - method: 'reset confirm', - example: - "beeper-desktop app:login:verification:recovery-key:reset confirm \\\n --access-token 'My Access Token' \\\n --recovery-key x", - }, - php: { - method: 'app->login->verification->recoveryKey->reset->confirm', - example: - "app->login->verification->recoveryKey->reset->confirm(\n recoveryKey: 'x'\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/login/verification/recovery-key/reset/confirm \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryKey": "x"\n }\'', - }, - }, - }, - { - name: 'list', - endpoint: '/v1/app/verifications', - httpMethod: 'get', - summary: 'List active verifications', - description: - 'List pending and active device verification transactions. Use this to recover state without a websocket connection.', - stainlessPath: '(resource) app.verifications > (method) list', - qualified: 'client.app.verifications.list', - response: - "{ items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]; }", - markdown: - "## list\n\n`client.app.verifications.list(): { items: object[]; }`\n\n**get** `/v1/app/verifications`\n\nList pending and active device verification transactions. Use this to recover state without a websocket connection.\n\n### Returns\n\n- `{ items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]; }`\n\n - `items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verifications = await client.app.verifications.list();\n\nconsole.log(verifications);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.list', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verifications = await client.app.verifications.list();\n\nconsole.log(verifications.items);", - }, - python: { - method: 'app.verifications.list', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverifications = client.app.verifications.list()\nprint(verifications.items)', - }, - go: { - method: 'client.App.Verifications.List', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverifications, err := client.App.Verifications.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verifications.Items)\n}\n', - }, - cli: { - method: 'verifications list', - example: "beeper-desktop app:verifications list \\\n --access-token 'My Access Token'", - }, - php: { - method: 'app->verifications->list', - example: - "app->verifications->list();\n\nvar_dump($verifications);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'create', - endpoint: '/v1/app/verifications', - httpMethod: 'post', - summary: 'Start device verification', - description: 'Start verifying this device from another signed-in device.', - stainlessPath: '(resource) app.verifications > (method) create', - qualified: 'client.app.verifications.create', - params: ["purpose?: 'login' | 'device';", 'userID?: string;'], - response: - "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", - markdown: - "## create\n\n`client.app.verifications.create(purpose?: 'login' | 'device', userID?: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications`\n\nStart verifying this device from another signed-in device.\n\n### Parameters\n\n- `purpose?: 'login' | 'device'`\n Why this verification is being started.\n\n- `userID?: string`\n User ID to verify. Defaults to the signed-in user.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.verifications.create();\n\nconsole.log(verification);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.create', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.verifications.create();\n\nconsole.log(verification.session);", - }, - python: { - method: 'app.verifications.create', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.verifications.create()\nprint(verification.session)', - }, - go: { - method: 'client.App.Verifications.New', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.Verifications.New(context.TODO(), beeperdesktopapi.AppVerificationNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.Session)\n}\n', - }, - cli: { - method: 'verifications create', - example: "beeper-desktop app:verifications create \\\n --access-token 'My Access Token'", - }, - php: { - method: 'app->verifications->create', - example: - "app->verifications->create(\n purpose: 'login', userID: 'userID'\n);\n\nvar_dump($verification);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'retrieve', - endpoint: '/v1/app/verifications/{verificationID}', - httpMethod: 'get', - summary: 'Get verification', - description: 'Get the current state of a device verification transaction.', - stainlessPath: '(resource) app.verifications > (method) retrieve', - qualified: 'client.app.verifications.retrieve', - params: ['verificationID: string;'], - response: - "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", - markdown: - "## retrieve\n\n`client.app.verifications.retrieve(verificationID: string): { session: object; verification?: object; }`\n\n**get** `/v1/app/verifications/{verificationID}`\n\nGet the current state of a device verification transaction.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.verifications.retrieve('x');\n\nconsole.log(verification);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.retrieve', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.verifications.retrieve('x');\n\nconsole.log(verification.session);", - }, - python: { - method: 'app.verifications.retrieve', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.verifications.retrieve(\n "x",\n)\nprint(verification.session)', - }, - go: { - method: 'client.App.Verifications.Get', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.Verifications.Get(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.Session)\n}\n', - }, - cli: { - method: 'verifications retrieve', - example: - "beeper-desktop app:verifications retrieve \\\n --access-token 'My Access Token' \\\n --verification-id x", - }, - php: { - method: 'app->verifications->retrieve', - example: - "app->verifications->retrieve('x');\n\nvar_dump($verification);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'accept', - endpoint: '/v1/app/verifications/{verificationID}/accept', - httpMethod: 'post', - summary: 'Accept device verification', - description: 'Accept an incoming device verification request.', - stainlessPath: '(resource) app.verifications > (method) accept', - qualified: 'client.app.verifications.accept', - params: ['verificationID: string;'], - response: - "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", - markdown: - "## accept\n\n`client.app.verifications.accept(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/accept`\n\nAccept an incoming device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.accept('x');\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.accept', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.accept('x');\n\nconsole.log(response.session);", - }, - python: { - method: 'app.verifications.accept', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.accept(\n "x",\n)\nprint(response.session)', - }, - go: { - method: 'client.App.Verifications.Accept', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Accept(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', - }, - cli: { - method: 'verifications accept', - example: - "beeper-desktop app:verifications accept \\\n --access-token 'My Access Token' \\\n --verification-id x", - }, - php: { - method: 'app->verifications->accept', - example: - "app->verifications->accept('x');\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/accept \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'cancel', - endpoint: '/v1/app/verifications/{verificationID}/cancel', - httpMethod: 'post', - summary: 'Cancel device verification', - description: 'Cancel an active device verification request.', - stainlessPath: '(resource) app.verifications > (method) cancel', - qualified: 'client.app.verifications.cancel', - params: ['verificationID: string;', 'code?: string;', 'reason?: string;'], - response: - "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", - markdown: - "## cancel\n\n`client.app.verifications.cancel(verificationID: string, code?: string, reason?: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/cancel`\n\nCancel an active device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n- `code?: string`\n Optional cancellation code.\n\n- `reason?: string`\n Optional user-facing cancellation reason.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.cancel('x');\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.cancel', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.cancel('x');\n\nconsole.log(response.session);", - }, - python: { - method: 'app.verifications.cancel', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.cancel(\n verification_id="x",\n)\nprint(response.session)', - }, - go: { - method: 'client.App.Verifications.Cancel', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Cancel(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.AppVerificationCancelParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', - }, - cli: { - method: 'verifications cancel', - example: - "beeper-desktop app:verifications cancel \\\n --access-token 'My Access Token' \\\n --verification-id x", - }, - php: { - method: 'app->verifications->cancel', - example: - "app->verifications->cancel(\n 'x', code: 'code', reason: 'reason'\n);\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/cancel \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'scan', - endpoint: '/v1/app/verifications/qr/scan', - httpMethod: 'post', - summary: 'Scan verification QR code', - description: 'Submit the QR code scanned from another signed-in device.', - stainlessPath: '(resource) app.verifications.qr > (method) scan', - qualified: 'client.app.verifications.qr.scan', - params: ['data: string;'], - response: - "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", - markdown: - "## scan\n\n`client.app.verifications.qr.scan(data: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/qr/scan`\n\nSubmit the QR code scanned from another signed-in device.\n\n### Parameters\n\n- `data: string`\n QR code payload scanned from the other device.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.qr.scan({ data: 'x' });\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.qr.scan', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.qr.scan({ data: 'x' });\n\nconsole.log(response.session);", - }, - python: { - method: 'app.verifications.qr.scan', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.qr.scan(\n data="x",\n)\nprint(response.session)', - }, - go: { - method: 'client.App.Verifications.Qr.Scan', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Qr.Scan(context.TODO(), beeperdesktopapi.AppVerificationQrScanParams{\n\t\tData: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', - }, - cli: { - method: 'qr scan', - example: - "beeper-desktop app:verifications:qr scan \\\n --access-token 'My Access Token' \\\n --data x", - }, - php: { - method: 'app->verifications->qr->scan', - example: - "app->verifications->qr->scan(data: 'x');\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications/qr/scan \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "data": "x"\n }\'', - }, - }, - }, - { - name: 'confirm_scanned', - endpoint: '/v1/app/verifications/{verificationID}/qr/confirm-scanned', - httpMethod: 'post', - summary: 'Confirm QR code scan', - description: 'Confirm that another device scanned this device QR code.', - stainlessPath: '(resource) app.verifications.qr > (method) confirm_scanned', - qualified: 'client.app.verifications.qr.confirmScanned', - params: ['verificationID: string;'], - response: - "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", - markdown: - "## confirm_scanned\n\n`client.app.verifications.qr.confirmScanned(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/qr/confirm-scanned`\n\nConfirm that another device scanned this device QR code.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.qr.confirmScanned('x');\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.qr.confirmScanned', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.qr.confirmScanned('x');\n\nconsole.log(response.session);", - }, - python: { - method: 'app.verifications.qr.confirm_scanned', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.qr.confirm_scanned(\n "x",\n)\nprint(response.session)', - }, - go: { - method: 'client.App.Verifications.Qr.ConfirmScanned', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Qr.ConfirmScanned(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', - }, - cli: { - method: 'qr confirm_scanned', - example: - "beeper-desktop app:verifications:qr confirm-scanned \\\n --access-token 'My Access Token' \\\n --verification-id x", - }, - php: { - method: 'app->verifications->qr->confirmScanned', - example: - "app->verifications->qr->confirmScanned('x');\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/qr/confirm-scanned \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'start', - endpoint: '/v1/app/verifications/{verificationID}/sas/start', - httpMethod: 'post', - summary: 'Start emoji verification', - description: 'Start emoji comparison for device verification.', - stainlessPath: '(resource) app.verifications.sas > (method) start', - qualified: 'client.app.verifications.sas.start', - params: ['verificationID: string;'], - response: - "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", - markdown: - "## start\n\n`client.app.verifications.sas.start(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/sas/start`\n\nStart emoji comparison for device verification.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.sas.start('x');\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.sas.start', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.sas.start('x');\n\nconsole.log(response.session);", - }, - python: { - method: 'app.verifications.sas.start', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.sas.start(\n "x",\n)\nprint(response.session)', - }, - go: { - method: 'client.App.Verifications.SAS.Start', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.SAS.Start(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', - }, - cli: { - method: 'sas start', - example: - "beeper-desktop app:verifications:sas start \\\n --access-token 'My Access Token' \\\n --verification-id x", - }, - php: { - method: 'app->verifications->sas->start', - example: - "app->verifications->sas->start('x');\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/sas/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, - { - name: 'confirm', - endpoint: '/v1/app/verifications/{verificationID}/sas/confirm', - httpMethod: 'post', - summary: 'Confirm emoji verification', - description: 'Confirm that the emoji or number sequence matches on both devices.', - stainlessPath: '(resource) app.verifications.sas > (method) confirm', - qualified: 'client.app.verifications.sas.confirm', - params: ['verificationID: string;'], - response: - "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", - markdown: - "## confirm\n\n`client.app.verifications.sas.confirm(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/verifications/{verificationID}/sas/confirm`\n\nConfirm that the emoji or number sequence matches on both devices.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.sas.confirm('x');\n\nconsole.log(response);\n```", - perLanguage: { - typescript: { - method: 'client.app.verifications.sas.confirm', - example: - "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.sas.confirm('x');\n\nconsole.log(response.session);", - }, - python: { - method: 'app.verifications.sas.confirm', - example: - 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.sas.confirm(\n "x",\n)\nprint(response.session)', - }, - go: { - method: 'client.App.Verifications.SAS.Confirm', - example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.SAS.Confirm(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', - }, - cli: { - method: 'sas confirm', - example: - "beeper-desktop app:verifications:sas confirm \\\n --access-token 'My Access Token' \\\n --verification-id x", - }, - php: { - method: 'app->verifications->sas->confirm', - example: - "app->verifications->sas->confirm('x');\n\nvar_dump($response);", - }, - http: { - example: - 'curl http://localhost:23373/v1/app/verifications/$VERIFICATION_ID/sas/confirm \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', - }, - }, - }, ]; const EMBEDDED_READMES: { language: string; content: string }[] = [ diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts index 2349c2fb..cf21e810 100644 --- a/packages/mcp-server/src/methods.ts +++ b/packages/mcp-server/src/methods.ts @@ -70,24 +70,6 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/v1/bridges/{bridgeID}/login-flows', }, - { - clientCallName: 'client.bridges.connections.retrieve', - fullyQualifiedName: 'bridges.connections.retrieve', - httpMethod: 'get', - httpPath: '/v1/bridges/{bridgeID}/connections/{loginID}', - }, - { - clientCallName: 'client.bridges.connections.list', - fullyQualifiedName: 'bridges.connections.list', - httpMethod: 'get', - httpPath: '/v1/bridges/{bridgeID}/connections', - }, - { - clientCallName: 'client.bridges.connections.remove', - fullyQualifiedName: 'bridges.connections.remove', - httpMethod: 'post', - httpPath: '/v1/bridges/{bridgeID}/connections/{loginID}/remove', - }, { clientCallName: 'client.bridges.loginSessions.create', fullyQualifiedName: 'bridges.loginSessions.create', @@ -262,108 +244,6 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/v1/info', }, - { - clientCallName: 'client.app.session', - fullyQualifiedName: 'app.session', - httpMethod: 'get', - httpPath: '/v1/app/session', - }, - { - clientCallName: 'client.app.login.email', - fullyQualifiedName: 'app.login.email', - httpMethod: 'post', - httpPath: '/v1/app/login/email', - }, - { - clientCallName: 'client.app.login.register', - fullyQualifiedName: 'app.login.register', - httpMethod: 'post', - httpPath: '/v1/app/login/register', - }, - { - clientCallName: 'client.app.login.response', - fullyQualifiedName: 'app.login.response', - httpMethod: 'post', - httpPath: '/v1/app/login/response', - }, - { - clientCallName: 'client.app.login.start', - fullyQualifiedName: 'app.login.start', - httpMethod: 'post', - httpPath: '/v1/app/login/start', - }, - { - clientCallName: 'client.app.login.verification.recoveryKey.verify', - fullyQualifiedName: 'app.login.verification.recoveryKey.verify', - httpMethod: 'post', - httpPath: '/v1/app/login/verification/recovery-key', - }, - { - clientCallName: 'client.app.login.verification.recoveryKey.reset.create', - fullyQualifiedName: 'app.login.verification.recoveryKey.reset.create', - httpMethod: 'post', - httpPath: '/v1/app/login/verification/recovery-key/reset', - }, - { - clientCallName: 'client.app.login.verification.recoveryKey.reset.confirm', - fullyQualifiedName: 'app.login.verification.recoveryKey.reset.confirm', - httpMethod: 'post', - httpPath: '/v1/app/login/verification/recovery-key/reset/confirm', - }, - { - clientCallName: 'client.app.verifications.create', - fullyQualifiedName: 'app.verifications.create', - httpMethod: 'post', - httpPath: '/v1/app/verifications', - }, - { - clientCallName: 'client.app.verifications.retrieve', - fullyQualifiedName: 'app.verifications.retrieve', - httpMethod: 'get', - httpPath: '/v1/app/verifications/{verificationID}', - }, - { - clientCallName: 'client.app.verifications.list', - fullyQualifiedName: 'app.verifications.list', - httpMethod: 'get', - httpPath: '/v1/app/verifications', - }, - { - clientCallName: 'client.app.verifications.accept', - fullyQualifiedName: 'app.verifications.accept', - httpMethod: 'post', - httpPath: '/v1/app/verifications/{verificationID}/accept', - }, - { - clientCallName: 'client.app.verifications.cancel', - fullyQualifiedName: 'app.verifications.cancel', - httpMethod: 'post', - httpPath: '/v1/app/verifications/{verificationID}/cancel', - }, - { - clientCallName: 'client.app.verifications.qr.confirmScanned', - fullyQualifiedName: 'app.verifications.qr.confirmScanned', - httpMethod: 'post', - httpPath: '/v1/app/verifications/{verificationID}/qr/confirm-scanned', - }, - { - clientCallName: 'client.app.verifications.qr.scan', - fullyQualifiedName: 'app.verifications.qr.scan', - httpMethod: 'post', - httpPath: '/v1/app/verifications/qr/scan', - }, - { - clientCallName: 'client.app.verifications.sas.confirm', - fullyQualifiedName: 'app.verifications.sas.confirm', - httpMethod: 'post', - httpPath: '/v1/app/verifications/{verificationID}/sas/confirm', - }, - { - clientCallName: 'client.app.verifications.sas.start', - fullyQualifiedName: 'app.verifications.sas.start', - httpMethod: 'post', - httpPath: '/v1/app/verifications/{verificationID}/sas/start', - }, ]; function allowedMethodsForCodeTool(options: McpOptions | undefined): SdkMethod[] | undefined { diff --git a/src/client.ts b/src/client.ts index 1d44dd43..49d3b8a3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -56,20 +56,9 @@ import { AccountRetrieveResponse, Accounts, } from './resources/accounts/accounts'; -import { - App, - AppSessionResponse, - LoginRegistrationRequiredResponse, - LoginResponse, - LoginResponseOutput, - RecoveryKeyResetResponse, - SessionMutationResponse, - Verification, - VerificationResponse, -} from './resources/app/app'; +import { App, Verification } from './resources/app/app'; import { Bridge, - BridgeConnection, BridgeListResponse, BridgeRetrieveResponse, Bridges, @@ -296,8 +285,8 @@ export class BaseBeeperDesktop { } /** - * Focus Beeper Desktop and optionally navigate to a specific chat, message, or - * pre-fill plain text and an image path. + * Focus Beeper Desktop and optionally open a specific chat, jump to a message, or + * pre-fill text and an image. * * @example * ```ts @@ -312,9 +301,9 @@ export class BaseBeeperDesktop { } /** - * Returns matching chats, participant name matches in groups, and the first page - * of messages in one call. Paginate messages via search-messages. Paginate chats - * via search-chats. + * Return matching chats, participant matches in group chats, and the first page of + * message results in one call. Use the dedicated chat and message search endpoints + * for pagination. * * @example * ```ts @@ -946,7 +935,6 @@ export declare namespace BeeperDesktop { export { Bridges as Bridges, type Bridge as Bridge, - type BridgeConnection as BridgeConnection, type CookieField as CookieField, type DisappearingTimerCapability as DisappearingTimerCapability, type GroupFieldCapability as GroupFieldCapability, @@ -1005,17 +993,7 @@ export declare namespace BeeperDesktop { export { Info as Info, type InfoRetrieveResponse as InfoRetrieveResponse }; - export { - App as App, - type LoginRegistrationRequiredResponse as LoginRegistrationRequiredResponse, - type LoginResponse as LoginResponse, - type LoginResponseOutput as LoginResponseOutput, - type RecoveryKeyResetResponse as RecoveryKeyResetResponse, - type SessionMutationResponse as SessionMutationResponse, - type Verification as Verification, - type VerificationResponse as VerificationResponse, - type AppSessionResponse as AppSessionResponse, - }; + export { App as App, type Verification as Verification }; export type APIError = API.APIError; export type AppStateSnapshot = API.AppStateSnapshot; diff --git a/src/resources/accounts/accounts.ts b/src/resources/accounts/accounts.ts index 4ac2f8ee..0be35e7f 100644 --- a/src/resources/accounts/accounts.ts +++ b/src/resources/accounts/accounts.ts @@ -21,7 +21,7 @@ export class BaseAccounts extends APIResource { static override readonly _key: readonly ['accounts'] = Object.freeze(['accounts'] as const); /** - * Get one Chat Account connected to this Beeper Desktop instance. + * Get one chat account connected to this Beeper Client API server. * * @example * ```ts @@ -33,8 +33,8 @@ export class BaseAccounts extends APIResource { } /** - * List Chat Accounts connected to this Beeper Desktop instance, including bridge - * metadata and network identity. + * List chat accounts connected to this Beeper Client API server, including bridge, + * network, user identity, and connection status. * * @example * ```ts @@ -93,8 +93,8 @@ export interface Account { capabilities?: { [key: string]: unknown }; /** - * Bridge login identity for this account, when known. This is not guaranteed to be - * one-to-one with accountID. + * Bridge login ID for this account, when known. One bridge login can contain + * multiple chat accounts. */ loginID?: string; @@ -115,14 +115,15 @@ export interface Account { */ export interface AccountBridge { /** - * Bridge instance identifier. Matrix and cloud bridges often use the bridge type - * (for example matrix or discordgo); local bridges use a local bridge ID (for - * example local-whatsapp). Available in Beeper Desktop v4.2.785+. + * Bridge identifier. Beeper Cloud accounts often use the network type (for example + * matrix or discordgo); on-device accounts use a local bridge ID (for example + * local-whatsapp). Available in Beeper Desktop v4.2.785+. */ id: string; /** - * Bridge provider for the account. Available in Beeper Desktop v4.2.785+. + * Where this account runs: on this device or in Beeper Cloud. Available in Beeper + * Desktop v4.2.785+. */ provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; @@ -174,8 +175,8 @@ export interface AccountRetrieveResponse { capabilities?: { [key: string]: unknown }; /** - * Bridge login identity for this account, when known. This is not guaranteed to be - * one-to-one with accountID. + * Bridge login ID for this account, when known. One bridge login can contain + * multiple chat accounts. */ loginID?: string; @@ -192,7 +193,7 @@ export interface AccountRetrieveResponse { } /** - * Accounts configured on this device. Includes accountID, bridge metadata, + * Chat accounts configured on this device. Includes accountID, bridge metadata, * optional network name, and user identity. */ export type AccountListResponse = Array; diff --git a/src/resources/accounts/contacts.ts b/src/resources/accounts/contacts.ts index 42bd7548..18ab023e 100644 --- a/src/resources/accounts/contacts.ts +++ b/src/resources/accounts/contacts.ts @@ -72,14 +72,14 @@ export interface ContactSearchResponse { export interface ContactListParams extends CursorSearchParams { /** - * Optional search query for blended contact lookup. + * Optional search query for contact lookup. */ query?: string; } export interface ContactSearchParams { /** - * Text to search users by. Network-specific behavior. + * Text to search contacts by. Matching behavior depends on the network. */ query: string; } diff --git a/src/resources/app/app.ts b/src/resources/app/app.ts index 65c05a3d..7edea82a 100644 --- a/src/resources/app/app.ts +++ b/src/resources/app/app.ts @@ -2,1332 +2,26 @@ import { APIResource } from '../../core/resource'; import * as LoginAPI from './login/login'; -import { - BaseLogin, - Login, - LoginEmailParams, - LoginEmailResponse, - LoginRegisterParams, - LoginRegisterResponse, - LoginResponseParams, - LoginResponseResponse, - LoginStartResponse, -} from './login/login'; +import { BaseLogin, Login } from './login/login'; import * as VerificationsAPI from './verifications/verifications'; -import { - BaseVerifications, - VerificationAcceptResponse, - VerificationCancelParams, - VerificationCancelResponse, - VerificationCreateParams, - VerificationCreateResponse, - VerificationListResponse, - VerificationRetrieveResponse, - Verifications, -} from './verifications/verifications'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; +import { BaseVerifications, Verifications } from './verifications/verifications'; /** * Manage Beeper app login and encrypted messaging setup */ export class BaseApp extends APIResource { static override readonly _key: readonly ['app'] = Object.freeze(['app'] as const); - - /** - * Return the current Beeper Desktop sign-in and encrypted messaging setup state. - * This endpoint is public before sign-in so apps can discover that login is - * needed; after sign-in, pass a read token. - */ - session(options?: RequestOptions): APIPromise { - return this._client.get('/v1/app/session', options); - } -} -/** - * Manage Beeper app login and encrypted messaging setup - */ -export class App extends BaseApp { - login: LoginAPI.Login = new LoginAPI.Login(this._client); - verifications: VerificationsAPI.Verifications = new VerificationsAPI.Verifications(this._client); -} - -export interface LoginRegistrationRequiredResponse { - /** - * Copy to display during account creation. - */ - copy: LoginRegistrationRequiredResponse.Copy; - - /** - * Registration token returned by Beeper. - */ - leadToken: string; - - /** - * Indicates that the user needs to create a Beeper account. - */ - registrationRequired: true; - - /** - * Login request ID to use when creating the account. - */ - request: string; - - /** - * Suggested usernames for the new account. - */ - usernameSuggestions?: Array; -} - -export namespace LoginRegistrationRequiredResponse { - /** - * Copy to display during account creation. - */ - export interface Copy { - /** - * Submit button label. - */ - submit: 'Continue'; - - /** - * Terms and privacy notice to show before account creation. - */ - terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; - - /** - * Title for the username step. - */ - title: 'Choose your username'; - - /** - * Placeholder for the username field. - */ - usernamePlaceholder: 'Username'; - } -} - -export interface LoginResponse { - /** - * Desktop API credentials for the signed-in app session. - */ - desktopAPI: LoginResponse.DesktopAPI; - - /** - * Account credentials for first-party app setup. - */ - matrix: LoginResponse.Matrix; - - /** - * Current app session state after sign-in. - */ - session: LoginResponse.Session; -} - -export namespace LoginResponse { - /** - * Desktop API credentials for the signed-in app session. - */ - export interface DesktopAPI { - /** - * Desktop API access token for this app session. - */ - accessToken: string; - - /** - * Granted Desktop API scopes. - */ - scope: 'read write'; - - /** - * Access token type. - */ - tokenType: 'Bearer'; - } - - /** - * Account credentials for first-party app setup. - */ - export interface Matrix { - /** - * Account access token. Returned once for first-party app setup. - */ - accessToken: string; - - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Current app session state after sign-in. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } -} - -export type LoginResponseOutput = LoginResponseOutput.UnionMember0 | LoginResponseOutput.UnionMember1; - -export namespace LoginResponseOutput { - export interface UnionMember0 { - /** - * Desktop API credentials for the signed-in app session. - */ - desktopAPI: UnionMember0.DesktopAPI; - - /** - * Account credentials for first-party app setup. - */ - matrix: UnionMember0.Matrix; - - /** - * Current app session state after sign-in. - */ - session: UnionMember0.Session; - } - - export namespace UnionMember0 { - /** - * Desktop API credentials for the signed-in app session. - */ - export interface DesktopAPI { - /** - * Desktop API access token for this app session. - */ - accessToken: string; - - /** - * Granted Desktop API scopes. - */ - scope: 'read write'; - - /** - * Access token type. - */ - tokenType: 'Bearer'; - } - - /** - * Account credentials for first-party app setup. - */ - export interface Matrix { - /** - * Account access token. Returned once for first-party app setup. - */ - accessToken: string; - - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Current app session state after sign-in. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - } - - export interface UnionMember1 { - /** - * Copy to display during account creation. - */ - copy: UnionMember1.Copy; - - /** - * Registration token returned by Beeper. - */ - leadToken: string; - - /** - * Indicates that the user needs to create a Beeper account. - */ - registrationRequired: true; - - /** - * Login request ID to use when creating the account. - */ - request: string; - - /** - * Suggested usernames for the new account. - */ - usernameSuggestions?: Array; - } - - export namespace UnionMember1 { - /** - * Copy to display during account creation. - */ - export interface Copy { - /** - * Submit button label. - */ - submit: 'Continue'; - - /** - * Terms and privacy notice to show before account creation. - */ - terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; - - /** - * Title for the username step. - */ - title: 'Choose your username'; - - /** - * Placeholder for the username field. - */ - usernamePlaceholder: 'Username'; - } - } -} - -export interface RecoveryKeyResetResponse { - /** - * New recovery key. Show it once and ask the user to save it. - */ - recoveryKey: string; - - /** - * Current session state after creating the new recovery key. - */ - session: RecoveryKeyResetResponse.Session; -} - -export namespace RecoveryKeyResetResponse { - /** - * Current session state after creating the new recovery key. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } -} - -export interface SessionMutationResponse { - /** - * Current app session state. - */ - session: SessionMutationResponse.Session; -} - -export namespace SessionMutationResponse { - /** - * Current app session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } +} +/** + * Manage Beeper app login and encrypted messaging setup + */ +export class App extends BaseApp { + login: LoginAPI.Login = new LoginAPI.Login(this._client); + verifications: VerificationsAPI.Verifications = new VerificationsAPI.Verifications(this._client); } /** - * Trusted-device verification progress. + * Trusted device verification progress. */ export interface Verification { /** @@ -1371,7 +65,7 @@ export interface Verification { otherDevice?: Verification.OtherDevice; /** - * Other user participating in verification. + * Other Beeper user participating in verification. */ otherUserID?: string; @@ -1443,678 +137,15 @@ export namespace Verification { } } -export interface VerificationResponse { - /** - * Current session state. - */ - session: VerificationResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: VerificationResponse.Verification; -} - -export namespace VerificationResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface AppSessionResponse { - /** - * Encrypted messaging setup status. - */ - e2ee: AppSessionResponse.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: AppSessionResponse.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: AppSessionResponse.Verification; -} - -export namespace AppSessionResponse { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - App.Login = Login; App.BaseLogin = BaseLogin; App.Verifications = Verifications; App.BaseVerifications = BaseVerifications; export declare namespace App { - export { - type LoginRegistrationRequiredResponse as LoginRegistrationRequiredResponse, - type LoginResponse as LoginResponse, - type LoginResponseOutput as LoginResponseOutput, - type RecoveryKeyResetResponse as RecoveryKeyResetResponse, - type SessionMutationResponse as SessionMutationResponse, - type Verification as Verification, - type VerificationResponse as VerificationResponse, - type AppSessionResponse as AppSessionResponse, - }; + export { type Verification as Verification }; - export { - Login as Login, - BaseLogin as BaseLogin, - type LoginEmailResponse as LoginEmailResponse, - type LoginRegisterResponse as LoginRegisterResponse, - type LoginResponseResponse as LoginResponseResponse, - type LoginStartResponse as LoginStartResponse, - type LoginEmailParams as LoginEmailParams, - type LoginRegisterParams as LoginRegisterParams, - type LoginResponseParams as LoginResponseParams, - }; + export { Login as Login, BaseLogin as BaseLogin }; - export { - Verifications as Verifications, - BaseVerifications as BaseVerifications, - type VerificationCreateResponse as VerificationCreateResponse, - type VerificationRetrieveResponse as VerificationRetrieveResponse, - type VerificationListResponse as VerificationListResponse, - type VerificationAcceptResponse as VerificationAcceptResponse, - type VerificationCancelResponse as VerificationCancelResponse, - type VerificationCreateParams as VerificationCreateParams, - type VerificationCancelParams as VerificationCancelParams, - }; + export { Verifications as Verifications, BaseVerifications as BaseVerifications }; } diff --git a/src/resources/app/index.ts b/src/resources/app/index.ts index 4771c1fd..1a24e59f 100644 --- a/src/resources/app/index.ts +++ b/src/resources/app/index.ts @@ -1,36 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { - App, - BaseApp, - type LoginRegistrationRequiredResponse, - type LoginResponse, - type LoginResponseOutput, - type RecoveryKeyResetResponse, - type SessionMutationResponse, - type Verification, - type VerificationResponse, - type AppSessionResponse, -} from './app'; -export { - Login, - BaseLogin, - type LoginEmailResponse, - type LoginRegisterResponse, - type LoginResponseResponse, - type LoginStartResponse, - type LoginEmailParams, - type LoginRegisterParams, - type LoginResponseParams, -} from './login/index'; -export { - Verifications, - BaseVerifications, - type VerificationCreateResponse, - type VerificationRetrieveResponse, - type VerificationListResponse, - type VerificationAcceptResponse, - type VerificationCancelResponse, - type VerificationCreateParams, - type VerificationCancelParams, -} from './verifications/index'; +export { App, BaseApp, type Verification } from './app'; +export { Login, BaseLogin } from './login/index'; +export { Verifications, BaseVerifications } from './verifications/index'; diff --git a/src/resources/app/login/index.ts b/src/resources/app/login/index.ts index 028b6329..b856af75 100644 --- a/src/resources/app/login/index.ts +++ b/src/resources/app/login/index.ts @@ -1,14 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { - Login, - BaseLogin, - type LoginEmailResponse, - type LoginRegisterResponse, - type LoginResponseResponse, - type LoginStartResponse, - type LoginEmailParams, - type LoginRegisterParams, - type LoginResponseParams, -} from './login'; +export { Login, BaseLogin } from './login'; export { Verification, BaseVerification } from './verification/index'; diff --git a/src/resources/app/login/login.ts b/src/resources/app/login/login.ts index 1238697e..920583d0 100644 --- a/src/resources/app/login/login.ts +++ b/src/resources/app/login/login.ts @@ -2,46 +2,13 @@ import { APIResource } from '../../../core/resource'; import * as VerificationAPI from './verification/verification'; -import { BaseVerification, Verification as VerificationAPIVerification } from './verification/verification'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; +import { BaseVerification, Verification } from './verification/verification'; /** * Complete first-party Beeper app login */ export class BaseLogin extends APIResource { static override readonly _key: readonly ['app', 'login'] = Object.freeze(['app', 'login'] as const); - - /** - * Send a sign-in code to the user email address. - */ - email(body: LoginEmailParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/email', { body, ...options, __security: {} }); - } - - /** - * Create a Beeper account after the user chooses a username and accepts the Terms - * of Use. - */ - register(body: LoginRegisterParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/register', { body, ...options, __security: {} }); - } - - /** - * Finish sign-in with the code sent to the user email address. If the user needs a - * new account, the response includes account creation copy and username - * suggestions. - */ - response(body: LoginResponseParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/response', { body, ...options, __security: {} }); - } - - /** - * Start a first-party Beeper Desktop sign-in session. - */ - start(options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/start', { ...options, __security: {} }); - } } /** * Complete first-party Beeper app login @@ -50,772 +17,9 @@ export class Login extends BaseLogin { verification: VerificationAPI.Verification = new VerificationAPI.Verification(this._client); } -export type LoginEmailResponse = unknown; - -export interface LoginRegisterResponse { - /** - * Desktop API credentials for the signed-in app session. - */ - desktopAPI: LoginRegisterResponse.DesktopAPI; - - /** - * Account credentials for first-party app setup. - */ - matrix: LoginRegisterResponse.Matrix; - - /** - * Current app session state after sign-in. - */ - session: LoginRegisterResponse.Session; -} - -export namespace LoginRegisterResponse { - /** - * Desktop API credentials for the signed-in app session. - */ - export interface DesktopAPI { - /** - * Desktop API access token for this app session. - */ - accessToken: string; - - /** - * Granted Desktop API scopes. - */ - scope: 'read write'; - - /** - * Access token type. - */ - tokenType: 'Bearer'; - } - - /** - * Account credentials for first-party app setup. - */ - export interface Matrix { - /** - * Account access token. Returned once for first-party app setup. - */ - accessToken: string; - - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Current app session state after sign-in. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } -} - -export type LoginResponseResponse = LoginResponseResponse.UnionMember0 | LoginResponseResponse.UnionMember1; - -export namespace LoginResponseResponse { - export interface UnionMember0 { - /** - * Desktop API credentials for the signed-in app session. - */ - desktopAPI: UnionMember0.DesktopAPI; - - /** - * Account credentials for first-party app setup. - */ - matrix: UnionMember0.Matrix; - - /** - * Current app session state after sign-in. - */ - session: UnionMember0.Session; - } - - export namespace UnionMember0 { - /** - * Desktop API credentials for the signed-in app session. - */ - export interface DesktopAPI { - /** - * Desktop API access token for this app session. - */ - accessToken: string; - - /** - * Granted Desktop API scopes. - */ - scope: 'read write'; - - /** - * Access token type. - */ - tokenType: 'Bearer'; - } - - /** - * Account credentials for first-party app setup. - */ - export interface Matrix { - /** - * Account access token. Returned once for first-party app setup. - */ - accessToken: string; - - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Current app session state after sign-in. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - } - - export interface UnionMember1 { - /** - * Copy to display during account creation. - */ - copy: UnionMember1.Copy; - - /** - * Registration token returned by Beeper. - */ - leadToken: string; - - /** - * Indicates that the user needs to create a Beeper account. - */ - registrationRequired: true; - - /** - * Login request ID to use when creating the account. - */ - request: string; - - /** - * Suggested usernames for the new account. - */ - usernameSuggestions?: Array; - } - - export namespace UnionMember1 { - /** - * Copy to display during account creation. - */ - export interface Copy { - /** - * Submit button label. - */ - submit: 'Continue'; - - /** - * Terms and privacy notice to show before account creation. - */ - terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; - - /** - * Title for the username step. - */ - title: 'Choose your username'; - - /** - * Placeholder for the username field. - */ - usernamePlaceholder: 'Username'; - } - } -} - -export interface LoginStartResponse { - /** - * Login request ID to use in the next sign-in step. - */ - request: string; - - /** - * Available sign-in methods for this request. - */ - type: Array; -} - -export interface LoginEmailParams { - /** - * Email address to send the sign-in code to. - */ - email: string; - - /** - * Login request ID returned by the start step. - */ - request: string; -} - -export interface LoginRegisterParams { - /** - * Confirms that the user accepted the Terms of Use and acknowledged the Privacy - * Policy. - */ - acceptTerms: true; - - /** - * Registration token returned by Beeper. - */ - leadToken: string; - - /** - * Login request ID returned by the start step. - */ - request: string; - - /** - * Username selected by the user. - */ - username: string; -} - -export interface LoginResponseParams { - /** - * Login request ID returned by the start step. - */ - request: string; - - /** - * Sign-in code from the user email. - */ - response: string; -} - -Login.Verification = VerificationAPIVerification; +Login.Verification = Verification; Login.BaseVerification = BaseVerification; export declare namespace Login { - export { - type LoginEmailResponse as LoginEmailResponse, - type LoginRegisterResponse as LoginRegisterResponse, - type LoginResponseResponse as LoginResponseResponse, - type LoginStartResponse as LoginStartResponse, - type LoginEmailParams as LoginEmailParams, - type LoginRegisterParams as LoginRegisterParams, - type LoginResponseParams as LoginResponseParams, - }; - - export { VerificationAPIVerification as Verification, BaseVerification as BaseVerification }; + export { Verification as Verification, BaseVerification as BaseVerification }; } diff --git a/src/resources/app/login/verification/index.ts b/src/resources/app/login/verification/index.ts index a24d5e5e..cde79e35 100644 --- a/src/resources/app/login/verification/index.ts +++ b/src/resources/app/login/verification/index.ts @@ -1,9 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { - RecoveryKey, - BaseRecoveryKey, - type RecoveryKeyVerifyResponse, - type RecoveryKeyVerifyParams, -} from './recovery-key/index'; +export { RecoveryKey, BaseRecoveryKey } from './recovery-key/index'; export { Verification, BaseVerification } from './verification'; diff --git a/src/resources/app/login/verification/recovery-key/index.ts b/src/resources/app/login/verification/recovery-key/index.ts index e0dbac2d..3e2be45d 100644 --- a/src/resources/app/login/verification/recovery-key/index.ts +++ b/src/resources/app/login/verification/recovery-key/index.ts @@ -1,16 +1,4 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { - RecoveryKey, - BaseRecoveryKey, - type RecoveryKeyVerifyResponse, - type RecoveryKeyVerifyParams, -} from './recovery-key'; -export { - Reset, - BaseReset, - type ResetCreateResponse, - type ResetConfirmResponse, - type ResetCreateParams, - type ResetConfirmParams, -} from './reset'; +export { RecoveryKey, BaseRecoveryKey } from './recovery-key'; +export { Reset, BaseReset } from './reset'; diff --git a/src/resources/app/login/verification/recovery-key/recovery-key.ts b/src/resources/app/login/verification/recovery-key/recovery-key.ts index 1be45f40..1de1a7e1 100644 --- a/src/resources/app/login/verification/recovery-key/recovery-key.ts +++ b/src/resources/app/login/verification/recovery-key/recovery-key.ts @@ -2,20 +2,8 @@ import { APIResource } from '../../../../../core/resource'; import * as ResetAPI from './reset'; -import { - BaseReset, - Reset, - ResetConfirmParams, - ResetConfirmResponse, - ResetCreateParams, - ResetCreateResponse, -} from './reset'; -import { APIPromise } from '../../../../../core/api-promise'; -import { RequestOptions } from '../../../../../internal/request-options'; +import { BaseReset, Reset } from './reset'; -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ export class BaseRecoveryKey extends APIResource { static override readonly _key: readonly ['app', 'login', 'verification', 'recoveryKey'] = Object.freeze([ 'app', @@ -23,305 +11,14 @@ export class BaseRecoveryKey extends APIResource { 'verification', 'recoveryKey', ] as const); - - /** - * Unlock encrypted messages with the user recovery key. - */ - verify(body: RecoveryKeyVerifyParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/verification/recovery-key', { body, ...options }); - } } -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ export class RecoveryKey extends BaseRecoveryKey { reset: ResetAPI.Reset = new ResetAPI.Reset(this._client); } -export interface RecoveryKeyVerifyResponse { - /** - * Current app session state. - */ - session: RecoveryKeyVerifyResponse.Session; -} - -export namespace RecoveryKeyVerifyResponse { - /** - * Current app session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } -} - -export interface RecoveryKeyVerifyParams { - /** - * Recovery key saved by the user. - */ - recoveryKey: string; -} - RecoveryKey.Reset = Reset; RecoveryKey.BaseReset = BaseReset; export declare namespace RecoveryKey { - export { - type RecoveryKeyVerifyResponse as RecoveryKeyVerifyResponse, - type RecoveryKeyVerifyParams as RecoveryKeyVerifyParams, - }; - - export { - Reset as Reset, - BaseReset as BaseReset, - type ResetCreateResponse as ResetCreateResponse, - type ResetConfirmResponse as ResetConfirmResponse, - type ResetCreateParams as ResetCreateParams, - type ResetConfirmParams as ResetConfirmParams, - }; + export { Reset as Reset, BaseReset as BaseReset }; } diff --git a/src/resources/app/login/verification/recovery-key/reset.ts b/src/resources/app/login/verification/recovery-key/reset.ts index a6ba60f7..278908d4 100644 --- a/src/resources/app/login/verification/recovery-key/reset.ts +++ b/src/resources/app/login/verification/recovery-key/reset.ts @@ -1,586 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../../../../core/resource'; -import { APIPromise } from '../../../../../core/api-promise'; -import { RequestOptions } from '../../../../../internal/request-options'; -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ export class BaseReset extends APIResource { static override readonly _key: readonly ['app', 'login', 'verification', 'recoveryKey', 'reset'] = Object.freeze(['app', 'login', 'verification', 'recoveryKey', 'reset'] as const); - - /** - * Create a new recovery key when the user cannot use the existing one. - */ - create( - body: ResetCreateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/v1/app/login/verification/recovery-key/reset', { body, ...options }); - } - - /** - * Confirm that the new recovery key should be used for this account. - */ - confirm(body: ResetConfirmParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/login/verification/recovery-key/reset/confirm', { body, ...options }); - } } -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ export class Reset extends BaseReset {} - -export interface ResetCreateResponse { - /** - * New recovery key. Show it once and ask the user to save it. - */ - recoveryKey: string; - - /** - * Current session state after creating the new recovery key. - */ - session: ResetCreateResponse.Session; -} - -export namespace ResetCreateResponse { - /** - * Current session state after creating the new recovery key. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } -} - -export interface ResetConfirmResponse { - /** - * Current app session state. - */ - session: ResetConfirmResponse.Session; -} - -export namespace ResetConfirmResponse { - /** - * Current app session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } -} - -export interface ResetCreateParams { - /** - * Existing recovery key, if the user has it. - */ - existingRecoveryKey?: string; -} - -export interface ResetConfirmParams { - /** - * New recovery key returned by the reset step. - */ - recoveryKey: string; -} - -export declare namespace Reset { - export { - type ResetCreateResponse as ResetCreateResponse, - type ResetConfirmResponse as ResetConfirmResponse, - type ResetCreateParams as ResetCreateParams, - type ResetConfirmParams as ResetConfirmParams, - }; -} diff --git a/src/resources/app/login/verification/verification.ts b/src/resources/app/login/verification/verification.ts index 0583568a..a1c86be7 100644 --- a/src/resources/app/login/verification/verification.ts +++ b/src/resources/app/login/verification/verification.ts @@ -2,12 +2,7 @@ import { APIResource } from '../../../../core/resource'; import * as RecoveryKeyAPI from './recovery-key/recovery-key'; -import { - BaseRecoveryKey, - RecoveryKey, - RecoveryKeyVerifyParams, - RecoveryKeyVerifyResponse, -} from './recovery-key/recovery-key'; +import { BaseRecoveryKey, RecoveryKey } from './recovery-key/recovery-key'; export class BaseVerification extends APIResource { static override readonly _key: readonly ['app', 'login', 'verification'] = Object.freeze([ @@ -24,10 +19,5 @@ Verification.RecoveryKey = RecoveryKey; Verification.BaseRecoveryKey = BaseRecoveryKey; export declare namespace Verification { - export { - RecoveryKey as RecoveryKey, - BaseRecoveryKey as BaseRecoveryKey, - type RecoveryKeyVerifyResponse as RecoveryKeyVerifyResponse, - type RecoveryKeyVerifyParams as RecoveryKeyVerifyParams, - }; + export { RecoveryKey as RecoveryKey, BaseRecoveryKey as BaseRecoveryKey }; } diff --git a/src/resources/app/verifications/index.ts b/src/resources/app/verifications/index.ts index a8a8aacb..995a801b 100644 --- a/src/resources/app/verifications/index.ts +++ b/src/resources/app/verifications/index.ts @@ -1,15 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Qr, BaseQr, type QrConfirmScannedResponse, type QrScanResponse, type QrScanParams } from './qr'; -export { SAS, BaseSAS, type SASConfirmResponse, type SASStartResponse } from './sas'; -export { - Verifications, - BaseVerifications, - type VerificationCreateResponse, - type VerificationRetrieveResponse, - type VerificationListResponse, - type VerificationAcceptResponse, - type VerificationCancelResponse, - type VerificationCreateParams, - type VerificationCancelParams, -} from './verifications'; +export { Qr, BaseQr } from './qr'; +export { SAS, BaseSAS } from './sas'; +export { Verifications, BaseVerifications } from './verifications'; diff --git a/src/resources/app/verifications/qr.ts b/src/resources/app/verifications/qr.ts index c55b805b..50724e09 100644 --- a/src/resources/app/verifications/qr.ts +++ b/src/resources/app/verifications/qr.ts @@ -1,818 +1,12 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ export class BaseQr extends APIResource { static override readonly _key: readonly ['app', 'verifications', 'qr'] = Object.freeze([ 'app', 'verifications', 'qr', ] as const); - - /** - * Confirm that another device scanned this device QR code. - */ - confirmScanned(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/v1/app/verifications/${verificationID}/qr/confirm-scanned`, options); - } - - /** - * Submit the QR code scanned from another signed-in device. - */ - scan(body: QrScanParams, options?: RequestOptions): APIPromise { - return this._client.post('/v1/app/verifications/qr/scan', { body, ...options }); - } } -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ export class Qr extends BaseQr {} - -export interface QrConfirmScannedResponse { - /** - * Current session state. - */ - session: QrConfirmScannedResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: QrConfirmScannedResponse.Verification; -} - -export namespace QrConfirmScannedResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface QrScanResponse { - /** - * Current session state. - */ - session: QrScanResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: QrScanResponse.Verification; -} - -export namespace QrScanResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface QrScanParams { - /** - * QR code payload scanned from the other device. - */ - data: string; -} - -export declare namespace Qr { - export { - type QrConfirmScannedResponse as QrConfirmScannedResponse, - type QrScanResponse as QrScanResponse, - type QrScanParams as QrScanParams, - }; -} diff --git a/src/resources/app/verifications/sas.ts b/src/resources/app/verifications/sas.ts index be3d4850..d805f9f8 100644 --- a/src/resources/app/verifications/sas.ts +++ b/src/resources/app/verifications/sas.ts @@ -1,807 +1,12 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../../core/resource'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ export class BaseSAS extends APIResource { static override readonly _key: readonly ['app', 'verifications', 'sas'] = Object.freeze([ 'app', 'verifications', 'sas', ] as const); - - /** - * Confirm that the emoji or number sequence matches on both devices. - */ - confirm(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/v1/app/verifications/${verificationID}/sas/confirm`, options); - } - - /** - * Start emoji comparison for device verification. - */ - start(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/v1/app/verifications/${verificationID}/sas/start`, options); - } } -/** - * First-party sign-in and encrypted messaging setup for Beeper Desktop. - */ export class SAS extends BaseSAS {} - -export interface SASConfirmResponse { - /** - * Current session state. - */ - session: SASConfirmResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: SASConfirmResponse.Verification; -} - -export namespace SASConfirmResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface SASStartResponse { - /** - * Current session state. - */ - session: SASStartResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: SASStartResponse.Verification; -} - -export namespace SASStartResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export declare namespace SAS { - export { type SASConfirmResponse as SASConfirmResponse, type SASStartResponse as SASStartResponse }; -} diff --git a/src/resources/app/verifications/verifications.ts b/src/resources/app/verifications/verifications.ts index a9dab4cd..ecd71b41 100644 --- a/src/resources/app/verifications/verifications.ts +++ b/src/resources/app/verifications/verifications.ts @@ -2,12 +2,9 @@ import { APIResource } from '../../../core/resource'; import * as QrAPI from './qr'; -import { BaseQr, Qr as QrAPIQr, QrConfirmScannedResponse, QrScanParams, QrScanResponse } from './qr'; +import { BaseQr, Qr } from './qr'; import * as SASAPI from './sas'; -import { BaseSAS, SAS as SasapiSAS, SASConfirmResponse, SASStartResponse } from './sas'; -import { APIPromise } from '../../../core/api-promise'; -import { RequestOptions } from '../../../internal/request-options'; -import { path } from '../../../internal/utils/path'; +import { BaseSAS, SAS } from './sas'; /** * Manage device verification transactions @@ -17,49 +14,6 @@ export class BaseVerifications extends APIResource { 'app', 'verifications', ] as const); - - /** - * Start verifying this device from another signed-in device. - */ - create( - body: VerificationCreateParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.post('/v1/app/verifications', { body, ...options }); - } - - /** - * Get the current state of a device verification transaction. - */ - retrieve(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/v1/app/verifications/${verificationID}`, options); - } - - /** - * List pending and active device verification transactions. Use this to recover - * state without a websocket connection. - */ - list(options?: RequestOptions): APIPromise { - return this._client.get('/v1/app/verifications', options); - } - - /** - * Accept an incoming device verification request. - */ - accept(verificationID: string, options?: RequestOptions): APIPromise { - return this._client.post(path`/v1/app/verifications/${verificationID}/accept`, options); - } - - /** - * Cancel an active device verification request. - */ - cancel( - verificationID: string, - body: VerificationCancelParams | null | undefined = {}, - options?: RequestOptions, - ): APIPromise { - return this._client.post(path`/v1/app/verifications/${verificationID}/cancel`, { body, ...options }); - } } /** * Manage device verification transactions @@ -69,1717 +23,13 @@ export class Verifications extends BaseVerifications { sas: SASAPI.SAS = new SASAPI.SAS(this._client); } -export interface VerificationCreateResponse { - /** - * Current session state. - */ - session: VerificationCreateResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: VerificationCreateResponse.Verification; -} - -export namespace VerificationCreateResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface VerificationRetrieveResponse { - /** - * Current session state. - */ - session: VerificationRetrieveResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: VerificationRetrieveResponse.Verification; -} - -export namespace VerificationRetrieveResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface VerificationListResponse { - items: Array; -} - -export namespace VerificationListResponse { - /** - * Trusted-device verification progress. - */ - export interface Item { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Item.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Item.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Item.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Item.SAS; - } - - export namespace Item { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface VerificationAcceptResponse { - /** - * Current session state. - */ - session: VerificationAcceptResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: VerificationAcceptResponse.Verification; -} - -export namespace VerificationAcceptResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface VerificationCancelResponse { - /** - * Current session state. - */ - session: VerificationCancelResponse.Session; - - /** - * Trusted-device verification progress. - */ - verification?: VerificationCancelResponse.Verification; -} - -export namespace VerificationCancelResponse { - /** - * Current session state. - */ - export interface Session { - /** - * Encrypted messaging setup status. - */ - e2ee: Session.E2EE; - - /** - * Current onboarding state for Beeper Desktop. - */ - state: - | 'needs-login' - | 'initializing' - | 'needs-cross-signing-setup' - | 'needs-verification' - | 'needs-secrets' - | 'needs-first-sync' - | 'ready'; - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - matrix?: Session.Matrix; - - /** - * Trusted-device verification progress. - */ - verification?: Session.Verification; - } - - export namespace Session { - /** - * Encrypted messaging setup status. - */ - export interface E2EE { - /** - * Whether this account can verify trusted devices. - */ - crossSigning: boolean; - - /** - * Whether the first encrypted message sync is complete. - */ - firstSyncDone: boolean; - - /** - * Whether the user confirmed that they saved their recovery key. - */ - hasBackedUpRecoveryKey: boolean; - - /** - * Whether encrypted messaging setup has started. - */ - initialized: boolean; - - /** - * Whether encrypted message backup is available. - */ - keyBackup: boolean; - - /** - * Encrypted messaging keys available on this device. - */ - secrets: E2EE.Secrets; - - /** - * Whether secure key storage is available. - */ - secretStorage: boolean; - - /** - * Whether this device is trusted for encrypted messages. - */ - verified: boolean; - - /** - * Unix timestamp for when the recovery key was created. - */ - recoveryKeyGeneratedAt?: number; - } - - export namespace E2EE { - /** - * Encrypted messaging keys available on this device. - */ - export interface Secrets { - /** - * Whether the account identity key is available. - */ - masterKey: boolean; - - /** - * Whether the encrypted message backup key is available. - */ - megolmBackupKey: boolean; - - /** - * Whether a recovery key is available. - */ - recoveryKey: boolean; - - /** - * Whether the device trust key is available. - */ - selfSigningKey: boolean; - - /** - * Whether the user trust key is available. - */ - userSigningKey: boolean; - } - } - - /** - * Signed-in account details. Omitted until sign-in is complete. - */ - export interface Matrix { - /** - * Current device ID. - */ - deviceID: string; - - /** - * Beeper server URL for this account. - */ - homeserver: string; - - /** - * Signed-in Beeper user ID. - */ - userID: string; - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } - } - - /** - * Trusted-device verification progress. - */ - export interface Verification { - /** - * Verification ID to pass in verification action paths. - */ - id: string; - - /** - * Verification actions that are valid for the current state. - */ - availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; - - /** - * Whether this device started or received the verification. - */ - direction: 'incoming' | 'outgoing'; - - /** - * Verification methods supported for this transaction. - */ - methods: Array<'qr' | 'sas'>; - - /** - * Why this verification exists. - */ - purpose: 'login' | 'device'; - - /** - * Current trusted-device verification state. - */ - state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; - - /** - * Verification error details, if verification stopped. - */ - error?: Verification.Error; - - /** - * Other device participating in verification. - */ - otherDevice?: Verification.OtherDevice; - - /** - * Other user participating in verification. - */ - otherUserID?: string; - - /** - * QR verification data. - */ - qr?: Verification.Qr; - - /** - * Emoji or number comparison data for verification. - */ - sas?: Verification.SAS; - } - - export namespace Verification { - /** - * Verification error details, if verification stopped. - */ - export interface Error { - /** - * Verification error code. - */ - code: string; - - /** - * User-facing verification error message. - */ - reason: string; - } - - /** - * Other device participating in verification. - */ - export interface OtherDevice { - /** - * Other device ID. - */ - id: string; - - /** - * Other device display name, if known. - */ - name?: string; - } - - /** - * QR verification data. - */ - export interface Qr { - /** - * QR code payload to display for verification. - */ - data: string; - } - - /** - * Emoji or number comparison data for verification. - */ - export interface SAS { - /** - * Emoji sequence to compare on both devices. - */ - emojis: string; - - /** - * Number sequence to compare on both devices. - */ - decimals?: string; - } - } -} - -export interface VerificationCreateParams { - /** - * Why this verification is being started. - */ - purpose?: 'login' | 'device'; - - /** - * User ID to verify. Defaults to the signed-in user. - */ - userID?: string; -} - -export interface VerificationCancelParams { - /** - * Optional cancellation code. - */ - code?: string; - - /** - * Optional user-facing cancellation reason. - */ - reason?: string; -} - -Verifications.Qr = QrAPIQr; +Verifications.Qr = Qr; Verifications.BaseQr = BaseQr; -Verifications.SAS = SasapiSAS; +Verifications.SAS = SAS; Verifications.BaseSAS = BaseSAS; export declare namespace Verifications { - export { - type VerificationCreateResponse as VerificationCreateResponse, - type VerificationRetrieveResponse as VerificationRetrieveResponse, - type VerificationListResponse as VerificationListResponse, - type VerificationAcceptResponse as VerificationAcceptResponse, - type VerificationCancelResponse as VerificationCancelResponse, - type VerificationCreateParams as VerificationCreateParams, - type VerificationCancelParams as VerificationCancelParams, - }; - - export { - QrAPIQr as Qr, - BaseQr as BaseQr, - type QrConfirmScannedResponse as QrConfirmScannedResponse, - type QrScanResponse as QrScanResponse, - type QrScanParams as QrScanParams, - }; + export { Qr as Qr, BaseQr as BaseQr }; - export { - SasapiSAS as SAS, - BaseSAS as BaseSAS, - type SASConfirmResponse as SASConfirmResponse, - type SASStartResponse as SASStartResponse, - }; + export { SAS as SAS, BaseSAS as BaseSAS }; } diff --git a/src/resources/assets.ts b/src/resources/assets.ts index 93203cf5..95d907a3 100644 --- a/src/resources/assets.ts +++ b/src/resources/assets.ts @@ -14,8 +14,8 @@ export class BaseAssets extends APIResource { static override readonly _key: readonly ['assets'] = Object.freeze(['assets'] as const); /** - * Download a Matrix file using its mxc:// or localmxc:// URL to the device running - * Beeper Desktop and return the local file URL. + * Download a file from an mxc:// or localmxc:// URL to the device running the + * Beeper Client API and return the local file URL. * * @example * ```ts @@ -51,7 +51,7 @@ export class BaseAssets extends APIResource { /** * 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 + * uploadID that can be referenced when sending a message or creating a draft * attachment. * * @example @@ -70,8 +70,8 @@ export class BaseAssets extends APIResource { /** * 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. + * that can be referenced when sending a message or creating a draft attachment. + * Alternative to the multipart upload endpoint. * * @example * ```ts @@ -200,7 +200,7 @@ export interface AssetUploadBase64Response { export interface AssetDownloadParams { /** - * Matrix content URL (mxc:// or localmxc://) for the file to download. + * Beeper media URL (mxc:// or localmxc://) for the file to download. */ url: string; } diff --git a/src/resources/bridges/bridges.ts b/src/resources/bridges/bridges.ts index c6640c32..e1d63ac5 100644 --- a/src/resources/bridges/bridges.ts +++ b/src/resources/bridges/bridges.ts @@ -5,14 +5,7 @@ import * as BridgesAPI from './bridges'; import * as Shared from '../shared'; import * as AccountsAPI from '../accounts/accounts'; import * as ConnectionsAPI from './connections'; -import { - BaseConnections, - ConnectionListResponse, - ConnectionRemoveParams, - ConnectionRemoveResponse, - ConnectionRetrieveParams, - Connections, -} from './connections'; +import { BaseConnections, Connections } from './connections'; import * as LoginFlowsAPI from './login-flows'; import { BaseLoginFlows, LoginFlowListResponse, LoginFlows } from './login-flows'; import * as LoginSessionsAPI from './login-sessions/login-sessions'; @@ -35,22 +28,24 @@ export class BaseBridges extends APIResource { static override readonly _key: readonly ['bridges'] = Object.freeze(['bridges'] as const); /** - * Get one bridge-backed account type and the connected accounts that use it. + * Get one bridge, including the chat accounts connected through it. */ retrieve(bridgeID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/v1/bridges/${bridgeID}`, options); } /** - * List bridge-backed account types that can be shown in add-account flows, grouped - * with connected accounts that use the same Account schema as GET /v1/accounts. + * List available bridges. A bridge is a chat-network connector that can connect or + * reconnect chat accounts. Connected accounts use the same Account schema as GET + * /v1/accounts. */ list(options?: RequestOptions): APIPromise { return this._client.get('/v1/bridges', options); } /** - * Get bridgev2 provisioning capabilities for a bridge. + * Get advanced network capabilities for a bridge. This endpoint is intended for + * clients that build custom connect or chat-creation flows. */ retrieveCapabilities(bridgeID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/v1/bridges/${bridgeID}/capabilities`, options); @@ -66,11 +61,11 @@ export class Bridges extends BaseBridges { } /** - * Bridge-backed account type that can be shown in add-account flows. + * Available bridge that can connect or reconnect chat accounts. */ export interface Bridge { /** - * Bridge instance identifier. Use with bridge login-flow endpoints. + * Bridge ID. Use with bridge endpoints. */ id: string; @@ -86,17 +81,17 @@ export interface Bridge { activeAccountCount: number; /** - * Human-friendly account type name shown in Beeper Desktop. + * Human-friendly bridge name shown in Beeper. */ displayName: string; /** - * Bridge provider. + * Where accounts for this bridge run: on this device or in Beeper Cloud. */ provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; /** - * Whether this bridge can currently be used to add an account. + * Whether this bridge can currently be used to connect new accounts. */ status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; @@ -106,7 +101,8 @@ export interface Bridge { supportsMultipleAccounts: boolean; /** - * Bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, or twitter. + * Underlying bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, + * or twitter. */ type: string; @@ -116,44 +112,30 @@ export interface Bridge { network?: string; /** - * Human-friendly status text matching Beeper Desktop account management language. + * Human-friendly status text matching Beeper account management language. */ statusText?: string; } -/** - * Durable bridge connection identity. This is not guaranteed to be one-to-one with - * a Desktop API account. - */ -export interface BridgeConnection { - bridgeID: string; - - loginID: string; - - removeScopes: Array<'current-device' | 'all-devices'>; - - status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; - - accountIDs?: Array; - - statusText?: string; - +export interface CookieField { /** - * User the account belongs to. + * Field ID to send back in the fields object. */ - user?: Shared.User; -} - -export interface CookieField { id: string; + /** + * Cookie, header, or local storage key to collect. + */ name?: string; + /** + * Browser storage source for this value. + */ type?: 'cookie' | 'header' | 'local_storage'; } /** - * bridgev2 disappearing timer capability. + * Disappearing-message timer capability. */ export interface DisappearingTimerCapability { types: Array<'' | 'after_read' | 'after_send'>; @@ -164,7 +146,7 @@ export interface DisappearingTimerCapability { } /** - * bridgev2 group field capability. + * Group creation field capability. */ export interface GroupFieldCapability { allowed: boolean; @@ -176,81 +158,114 @@ export interface GroupFieldCapability { required?: boolean; /** - * bridgev2 disappearing timer capability. + * Disappearing-message timer capability. */ settings?: DisappearingTimerCapability; } /** - * bridgev2 group type capabilities. + * Group creation capabilities for one group type. */ export interface GroupTypeCapabilities { type_description: string; /** - * bridgev2 group field capability. + * Group creation field capability. */ avatar?: GroupFieldCapability; /** - * bridgev2 group field capability. + * Group creation field capability. */ disappear?: GroupFieldCapability; /** - * bridgev2 group field capability. + * Group creation field capability. */ name?: GroupFieldCapability; /** - * bridgev2 group field capability. + * Group creation field capability. */ parent?: GroupFieldCapability; /** - * bridgev2 group field capability. + * Group creation field capability. */ participants?: GroupFieldCapability; /** - * bridgev2 group field capability. + * Group creation field capability. */ topic?: GroupFieldCapability; /** - * bridgev2 group field capability. + * Group creation field capability. */ username?: GroupFieldCapability; } /** - * Bridge login flow. + * Connect or reconnect flow option for a bridge. */ export interface LoginFlow { + /** + * Flow ID to pass when creating a bridge login session. + */ id: string; + /** + * Short explanation for when to use this flow, when provided. + */ description?: string; + /** + * Display name for the flow, when provided. + */ name?: string; } export interface LoginInputField { + /** + * Field ID to send back in the fields object. + */ id: string; + /** + * Initial field value, when provided by the network. + */ initialValue?: string; + /** + * Field label to show to the user. + */ label?: string; + /** + * True if the user can leave this field empty. + */ optional?: boolean; + /** + * Placeholder text to show when the field is empty. + */ placeholder?: string; + /** + * Suggested input type, such as text, password, or email. + */ type?: string; } export interface LoginSession { + /** + * Bridge ID. + */ bridgeID: string; + /** + * Temporary bridge login session ID. + */ loginSessionID: string; status: @@ -266,14 +281,15 @@ export interface LoginSession { */ account?: AccountsAPI.Account; + /** + * Chat account ID for reconnect flows, when known. + */ accountID?: string; /** - * Durable bridge connection identity. This is not guaranteed to be one-to-one with - * a Desktop API account. + * Step the client should show or complete next. Omitted when the session is + * complete, cancelled, or failed. */ - connection?: BridgeConnection; - currentStep?: | LoginSession.UserInput | LoginSession.Cookies @@ -282,6 +298,15 @@ export interface LoginSession { error?: Shared.APIError; + /** + * Signed-in identity for a bridge. One bridge login can contain multiple chat + * accounts. + */ + login?: LoginSession.Login; + + /** + * Bridge login ID for reconnect flows, when known. + */ loginID?: string; } @@ -295,6 +320,9 @@ export namespace LoginSession { attachments?: Array; + /** + * User-facing instructions for this step. + */ instructions?: string; } @@ -305,29 +333,48 @@ export namespace LoginSession { type: 'cookies'; + /** + * URL to open for the user. + */ url: string; + /** + * Regular expression that identifies the final URL after sign-in. + */ expectedFinalURLRegex?: string; + /** + * Optional extraction script for browser-based sign-in helpers. Treat as an opaque + * helper value. + */ extractJS?: string; + /** + * User-facing instructions for this browser step. + */ instructions?: string; + /** + * Suggested user agent for the browser session. + */ userAgent?: string; } export interface DisplayAndWait { - display: DisplayAndWait.Qr | DisplayAndWait.Emoji | DisplayAndWait.Nothing; + display: DisplayAndWait.QrCode | DisplayAndWait.Emoji | DisplayAndWait.Empty; stepID: string; type: 'display_and_wait'; + /** + * User-facing instructions for this step. + */ instructions?: string; } export namespace DisplayAndWait { - export interface Qr { + export interface QrCode { data: string; type: 'qr'; @@ -339,7 +386,7 @@ export namespace LoginSession { type: 'emoji'; } - export interface Nothing { + export interface Empty { type: 'nothing'; } } @@ -353,25 +400,100 @@ export namespace LoginSession { account?: AccountsAPI.Account; /** - * Durable bridge connection identity. This is not guaranteed to be one-to-one with - * a Desktop API account. + * Completion instructions, when provided. */ - connection?: BridgesAPI.BridgeConnection; - instructions?: string; + /** + * Signed-in identity for a bridge. One bridge login can contain multiple chat + * accounts. + */ + login?: Complete.Login; + stepID?: string; } + + export namespace Complete { + /** + * Signed-in identity for a bridge. One bridge login can contain multiple chat + * accounts. + */ + export interface Login { + /** + * Bridge ID. + */ + bridgeID: string; + + /** + * Bridge login ID. + */ + loginID: string; + + removeScopes: Array<'current-device' | 'all-devices'>; + + status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; + + /** + * Chat accounts that belong to this bridge login, when known. + */ + accountIDs?: Array; + + /** + * Human-friendly bridge login status text. + */ + statusText?: string; + + /** + * User the account belongs to. + */ + user?: Shared.User; + } + } + + /** + * Signed-in identity for a bridge. One bridge login can contain multiple chat + * accounts. + */ + export interface Login { + /** + * Bridge ID. + */ + bridgeID: string; + + /** + * Bridge login ID. + */ + loginID: string; + + removeScopes: Array<'current-device' | 'all-devices'>; + + status: 'connected' | 'connecting' | 'needs_login' | 'logged_out' | 'unknown'; + + /** + * Chat accounts that belong to this bridge login, when known. + */ + accountIDs?: Array; + + /** + * Human-friendly bridge login status text. + */ + statusText?: string; + + /** + * User the account belongs to. + */ + user?: Shared.User; + } } /** - * bridgev2 provisioning capabilities. + * Advanced network capabilities for account lookup and group creation. */ export interface ProvisioningCapabilities { group_creation: { [key: string]: GroupTypeCapabilities }; /** - * bridgev2 resolve_identifier capabilities. + * Identifier lookup capabilities for this bridge. */ resolve_identifier: ResolveIdentifierCapabilities; @@ -379,7 +501,7 @@ export interface ProvisioningCapabilities { } /** - * bridgev2 resolve_identifier capabilities. + * Identifier lookup capabilities for this bridge. */ export interface ResolveIdentifierCapabilities { any_phone: boolean; @@ -398,11 +520,11 @@ export interface ResolveIdentifierCapabilities { } /** - * Bridge-backed account type that can be shown in add-account flows. + * Available bridge that can connect or reconnect chat accounts. */ export interface BridgeRetrieveResponse { /** - * Bridge instance identifier. Use with bridge login-flow endpoints. + * Bridge ID. Use with bridge endpoints. */ id: string; @@ -418,17 +540,17 @@ export interface BridgeRetrieveResponse { activeAccountCount: number; /** - * Human-friendly account type name shown in Beeper Desktop. + * Human-friendly bridge name shown in Beeper. */ displayName: string; /** - * Bridge provider. + * Where accounts for this bridge run: on this device or in Beeper Cloud. */ provider: 'cloud' | 'self-hosted' | 'local' | 'platform-sdk'; /** - * Whether this bridge can currently be used to add an account. + * Whether this bridge can currently be used to connect new accounts. */ status: 'available' | 'connected' | 'limit_reached' | 'temporarily_unavailable' | 'disabled'; @@ -438,7 +560,8 @@ export interface BridgeRetrieveResponse { supportsMultipleAccounts: boolean; /** - * Bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, or twitter. + * Underlying bridge type, such as matrix, discordgo, slackgo, whatsapp, telegram, + * or twitter. */ type: string; @@ -448,13 +571,13 @@ export interface BridgeRetrieveResponse { network?: string; /** - * Human-friendly status text matching Beeper Desktop account management language. + * Human-friendly status text matching Beeper account management language. */ statusText?: string; } /** - * Bridge-backed account types and their connected accounts. + * Available bridges and their connected accounts. */ export interface BridgeListResponse { items: Array; @@ -470,7 +593,6 @@ Bridges.BaseLoginSessions = BaseLoginSessions; export declare namespace Bridges { export { type Bridge as Bridge, - type BridgeConnection as BridgeConnection, type CookieField as CookieField, type DisappearingTimerCapability as DisappearingTimerCapability, type GroupFieldCapability as GroupFieldCapability, @@ -490,14 +612,7 @@ export declare namespace Bridges { type LoginFlowListResponse as LoginFlowListResponse, }; - export { - Connections as Connections, - BaseConnections as BaseConnections, - type ConnectionListResponse as ConnectionListResponse, - type ConnectionRemoveResponse as ConnectionRemoveResponse, - type ConnectionRetrieveParams as ConnectionRetrieveParams, - type ConnectionRemoveParams as ConnectionRemoveParams, - }; + export { Connections as Connections, BaseConnections as BaseConnections }; export { LoginSessions as LoginSessions, diff --git a/src/resources/bridges/connections.ts b/src/resources/bridges/connections.ts index 84f3e499..cee82417 100644 --- a/src/resources/bridges/connections.ts +++ b/src/resources/bridges/connections.ts @@ -1,102 +1,11 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../core/resource'; -import * as BridgesAPI from './bridges'; -import { APIPromise } from '../../core/api-promise'; -import { RequestOptions } from '../../internal/request-options'; -import { path } from '../../internal/utils/path'; -/** - * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. - */ export class BaseConnections extends APIResource { static override readonly _key: readonly ['bridges', 'connections'] = Object.freeze([ 'bridges', 'connections', ] as const); - - /** - * Get one durable bridge connection identity. - */ - retrieve( - loginID: string, - params: ConnectionRetrieveParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID } = params; - return this._client.get(path`/v1/bridges/${bridgeID}/connections/${loginID}`, options); - } - - /** - * List durable bridge connection identities for a bridge. - */ - list(bridgeID: string, options?: RequestOptions): APIPromise { - return this._client.get(path`/v1/bridges/${bridgeID}/connections`, options); - } - - /** - * Remove a bridge connection from this device or from all devices. - */ - remove( - loginID: string, - params: ConnectionRemoveParams, - options?: RequestOptions, - ): APIPromise { - const { bridgeID, ...body } = params; - return this._client.post(path`/v1/bridges/${bridgeID}/connections/${loginID}/remove`, { - body, - ...options, - }); - } } -/** - * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. - */ export class Connections extends BaseConnections {} - -export interface ConnectionListResponse { - items: Array; -} - -export interface ConnectionRemoveResponse { - bridgeID: string; - - loginID: string; - - /** - * Where this bridge connection should be removed. - */ - scope: 'current-device' | 'all-devices'; - - status: 'removed'; - - affectedAccountIDs?: Array; -} - -export interface ConnectionRetrieveParams { - /** - * Bridge ID. - */ - bridgeID: string; -} - -export interface ConnectionRemoveParams { - /** - * Path param: Bridge ID. - */ - bridgeID: string; - - /** - * Body param: Where this bridge connection should be removed. - */ - scope: 'current-device' | 'all-devices'; -} - -export declare namespace Connections { - export { - type ConnectionListResponse as ConnectionListResponse, - type ConnectionRemoveResponse as ConnectionRemoveResponse, - type ConnectionRetrieveParams as ConnectionRetrieveParams, - type ConnectionRemoveParams as ConnectionRemoveParams, - }; -} diff --git a/src/resources/bridges/index.ts b/src/resources/bridges/index.ts index c416019d..1ecd2307 100644 --- a/src/resources/bridges/index.ts +++ b/src/resources/bridges/index.ts @@ -4,7 +4,6 @@ export { Bridges, BaseBridges, type Bridge, - type BridgeConnection, type CookieField, type DisappearingTimerCapability, type GroupFieldCapability, @@ -17,14 +16,7 @@ export { type BridgeRetrieveResponse, type BridgeListResponse, } from './bridges'; -export { - Connections, - BaseConnections, - type ConnectionListResponse, - type ConnectionRemoveResponse, - type ConnectionRetrieveParams, - type ConnectionRemoveParams, -} from './connections'; +export { Connections, BaseConnections } from './connections'; export { LoginFlows, BaseLoginFlows, type LoginFlowListResponse } from './login-flows'; export { LoginSessions, diff --git a/src/resources/bridges/login-flows.ts b/src/resources/bridges/login-flows.ts index e10929cb..aeb4c96f 100644 --- a/src/resources/bridges/login-flows.ts +++ b/src/resources/bridges/login-flows.ts @@ -7,7 +7,7 @@ import { RequestOptions } from '../../internal/request-options'; import { path } from '../../internal/utils/path'; /** - * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + * Available bridges, bridge logins, login sessions for connect and reconnect flows, and advanced network capabilities. */ export class BaseLoginFlows extends APIResource { static override readonly _key: readonly ['bridges', 'loginFlows'] = Object.freeze([ @@ -16,14 +16,15 @@ export class BaseLoginFlows extends APIResource { ] as const); /** - * List bridge login flows that can be used to start a bridge login session. + * List connect and reconnect flow options for a bridge. Use a flowID when creating + * a bridge login session. */ list(bridgeID: string, options?: RequestOptions): APIPromise { return this._client.get(path`/v1/bridges/${bridgeID}/login-flows`, options); } } /** - * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + * Available bridges, bridge logins, login sessions for connect and reconnect flows, and advanced network capabilities. */ export class LoginFlows extends BaseLoginFlows {} diff --git a/src/resources/bridges/login-sessions/login-sessions.ts b/src/resources/bridges/login-sessions/login-sessions.ts index 3297f59e..ecd5290b 100644 --- a/src/resources/bridges/login-sessions/login-sessions.ts +++ b/src/resources/bridges/login-sessions/login-sessions.ts @@ -9,7 +9,7 @@ import { RequestOptions } from '../../../internal/request-options'; import { path } from '../../../internal/utils/path'; /** - * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + * Available bridges, bridge logins, login sessions for connect and reconnect flows, and advanced network capabilities. */ export class BaseLoginSessions extends APIResource { static override readonly _key: readonly ['bridges', 'loginSessions'] = Object.freeze([ @@ -18,8 +18,9 @@ export class BaseLoginSessions extends APIResource { ] as const); /** - * Start an add-account or reconnect flow for a bridge. Omit loginID/accountID to - * add a new account. + * Start a temporary bridge login session to connect a new chat account or + * reconnect an existing bridge login. Omit loginID and accountID to connect a new + * account. */ create( bridgeID: string, @@ -54,7 +55,7 @@ export class BaseLoginSessions extends APIResource { } } /** - * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + * Available bridges, bridge logins, login sessions for connect and reconnect flows, and advanced network capabilities. */ export class LoginSessions extends BaseLoginSessions { steps: StepsAPI.Steps = new StepsAPI.Steps(this._client); @@ -69,10 +70,20 @@ export interface LoginSessionCancelResponse { } export interface LoginSessionCreateParams { + /** + * Existing chat account ID to reconnect. Omit to connect a new account. + */ accountID?: string; + /** + * Optional flow ID returned by the list login flows endpoint. If omitted, Beeper + * chooses the default flow. + */ flowID?: string; + /** + * Existing bridge login ID to reconnect. Omit to connect a new account. + */ loginID?: string; } diff --git a/src/resources/bridges/login-sessions/steps.ts b/src/resources/bridges/login-sessions/steps.ts index b05938fe..bfffab1c 100644 --- a/src/resources/bridges/login-sessions/steps.ts +++ b/src/resources/bridges/login-sessions/steps.ts @@ -7,7 +7,7 @@ import { RequestOptions } from '../../../internal/request-options'; import { path } from '../../../internal/utils/path'; /** - * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + * Available bridges, bridge logins, login sessions for connect and reconnect flows, and advanced network capabilities. */ export class BaseSteps extends APIResource { static override readonly _key: readonly ['bridges', 'loginSessions', 'steps'] = Object.freeze([ @@ -32,7 +32,7 @@ export class BaseSteps extends APIResource { } } /** - * Bridge-backed account types, bridge connections, login sessions, and bridgev2 capabilities. + * Available bridges, bridge logins, login sessions for connect and reconnect flows, and advanced network capabilities. */ export class Steps extends BaseSteps {} @@ -53,17 +53,18 @@ export interface StepSubmitParams { type: 'user_input' | 'cookies' | 'display_and_wait'; /** - * Body param + * Body param: Field values keyed by the field IDs from the current step. */ fields?: { [key: string]: string }; /** - * Body param + * Body param: Last browser URL reached during a cookies step, if available. */ lastURL?: string; /** - * Body param + * Body param: How the step was completed. Omit unless the client needs to + * distinguish an embedded webview or browser extension. */ source?: 'api' | 'webview' | 'browser_extension'; } diff --git a/src/resources/chats/chats.ts b/src/resources/chats/chats.ts index 03f7ade9..851cd424 100644 --- a/src/resources/chats/chats.ts +++ b/src/resources/chats/chats.ts @@ -41,7 +41,7 @@ export class BaseChats extends APIResource { } /** - * Retrieve chat details including metadata, participants, and latest message + * Retrieve chat details, including metadata, participants, and the latest message. * * @example * ```ts @@ -59,7 +59,7 @@ export class BaseChats extends APIResource { } /** - * Update supported chat fields. Non-empty draft objects are accepted only when the + * Update supported chat fields. Non-empty drafts are accepted only when the * current draft is empty. Send draft=null to clear the draft before setting new * draft text or attachments. * @@ -98,8 +98,8 @@ export class BaseChats extends APIResource { } /** - * Archive or unarchive a chat. Set archived=true to move to archive, - * archived=false to move back to inbox + * Archive or unarchive a chat. Set archived=true to move it to Archive, or + * archived=false to move it back to the inbox. * * @example * ```ts @@ -157,8 +157,9 @@ export class BaseChats extends APIResource { } /** - * Force a delivery notification when supported by the underlying network. - * Currently intended for iMessage on macOS; unsupported networks return an error. + * Send a notification despite the recipient focus state when the network supports + * it. Currently intended for iMessage on macOS; unsupported networks return an + * error. * * @example * ```ts @@ -195,7 +196,7 @@ export class BaseChats extends APIResource { /** * 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+. + * direct chat when one is found. Available in Beeper v4.2.808+. * * @example * ```ts @@ -318,7 +319,7 @@ export interface Chat { lastReadMessageSortKey?: string; /** - * Local chat ID specific to this Beeper Desktop installation. + * Local chat ID specific to this installation. */ localChatID?: string | null; @@ -375,7 +376,7 @@ export namespace Chat { isAdmin?: boolean; /** - * True if this participant represents a network or bridge bot. + * True if this participant represents an automated network account. */ isNetworkBot?: boolean; @@ -735,7 +736,7 @@ export namespace Chat { */ export interface Draft { /** - * Matrix HTML draft body. + * Rich-text draft body as returned by Beeper. */ text: string; @@ -838,13 +839,12 @@ export namespace Chat { export interface ChatCreateResponse extends Chat { /** - * @deprecated DEPRECATED - use id instead. Compatibility alias for older clients. + * @deprecated Use id instead. */ chatID: string; /** - * @deprecated DEPRECATED - legacy start-chat status for older clients. New clients - * should inspect the returned Chat instead. + * @deprecated Inspect the returned Chat instead. */ status?: 'existing' | 'created'; } @@ -861,13 +861,12 @@ export interface ChatListResponse extends Chat { export interface ChatStartResponse extends Chat { /** - * @deprecated DEPRECATED - use id instead. Compatibility alias for older clients. + * @deprecated Use id instead. */ chatID: string; /** - * @deprecated DEPRECATED - legacy start-chat status for older clients. New clients - * should inspect the returned Chat instead. + * @deprecated Inspect the returned Chat instead. */ status?: 'existing' | 'created'; } @@ -968,8 +967,8 @@ export namespace ChatUpdateParams { */ export interface Draft { /** - * Draft text. Plain text and Markdown are converted to Matrix HTML with the same - * rules used by send and edit. + * Draft text. Plain text and Markdown are converted to Beeper rich text with the + * same rules used by send and edit. */ text: string; @@ -1064,8 +1063,7 @@ export interface ChatNotifyAnywayParams {} export interface ChatSearchParams extends CursorSearchParams { /** - * Provide an array of account IDs to filter chats from specific messaging accounts - * only + * Limit results to specific chat accounts. */ accountIDs?: Array; @@ -1082,20 +1080,18 @@ export interface ChatSearchParams extends CursorSearchParams { includeMuted?: boolean | null; /** - * Provide an ISO datetime string to only retrieve chats with last activity after - * this time + * Only include chats with last activity after this ISO 8601 datetime. */ lastActivityAfter?: string; /** - * Provide an ISO datetime string to only retrieve chats with last activity before - * this time + * Only include chats with last activity before this ISO 8601 datetime. */ lastActivityBefore?: string; /** - * Literal token search (non-semantic). Use single words users type (e.g., - * "dinner"). When multiple words provided, ALL must match. Case-insensitive. + * Literal chat search. Use words the user typed, such as "dinner". When multiple + * words are provided, all must match. Case-insensitive. */ query?: string; @@ -1124,7 +1120,7 @@ export interface ChatStartParams { accountID: string; /** - * Merged user-like contact payload used to resolve the best identifier. + * Contact-like user payload used to resolve the best identifier. */ user: ChatStartParams.User; @@ -1141,7 +1137,7 @@ export interface ChatStartParams { export namespace ChatStartParams { /** - * Merged user-like contact payload used to resolve the best identifier. + * Contact-like user payload used to resolve the best identifier. */ export interface User { /** diff --git a/src/resources/chats/messages/reactions.ts b/src/resources/chats/messages/reactions.ts index ae246981..97d4b94d 100644 --- a/src/resources/chats/messages/reactions.ts +++ b/src/resources/chats/messages/reactions.ts @@ -69,8 +69,8 @@ export class Reactions extends BaseReactions {} export interface ReactionDeleteResponse { /** - * Chat ID. Input routes also accept the local chat ID from this Beeper Desktop - * installation when available. + * Chat ID. Input routes also accept the local chat ID from this installation when + * available. */ chatID: string; @@ -93,8 +93,8 @@ export interface ReactionDeleteResponse { export interface ReactionAddResponse { /** - * Chat ID. Input routes also accept the local chat ID from this Beeper Desktop - * installation when available. + * Chat ID. Input routes also accept the local chat ID from this installation when + * available. */ chatID: string; @@ -122,8 +122,8 @@ export interface ReactionAddResponse { export interface ReactionDeleteParams { /** - * Chat ID. Input routes also accept the local chat ID from this Beeper Desktop - * installation when available. + * Chat ID. Input routes also accept the local chat ID from this installation when + * available. */ chatID: string; @@ -135,8 +135,8 @@ export interface ReactionDeleteParams { export interface ReactionAddParams { /** - * Path param: Chat ID. Input routes also accept the local chat ID from this Beeper - * Desktop installation when available. + * Path param: Chat ID. Input routes also accept the local chat ID from this + * installation when available. */ chatID: string; diff --git a/src/resources/chats/reminders.ts b/src/resources/chats/reminders.ts index ae959be1..904a6ecf 100644 --- a/src/resources/chats/reminders.ts +++ b/src/resources/chats/reminders.ts @@ -16,7 +16,7 @@ export class BaseReminders extends APIResource { ] as const); /** - * Set a reminder for a chat at a specific time + * Set a reminder for a chat at a specific time. * * @example * ```ts @@ -35,7 +35,7 @@ export class BaseReminders extends APIResource { } /** - * Clear an existing reminder from a chat + * Clear an existing reminder from a chat. * * @example * ```ts diff --git a/src/resources/index.ts b/src/resources/index.ts index 6ab15bb4..60dd458a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -9,18 +9,7 @@ export { type AccountRetrieveResponse, type AccountListResponse, } from './accounts/accounts'; -export { - App, - BaseApp, - type LoginRegistrationRequiredResponse, - type LoginResponse, - type LoginResponseOutput, - type RecoveryKeyResetResponse, - type SessionMutationResponse, - type Verification, - type VerificationResponse, - type AppSessionResponse, -} from './app/app'; +export { App, BaseApp, type Verification } from './app/app'; export { Assets, BaseAssets, @@ -36,7 +25,6 @@ export { Bridges, BaseBridges, type Bridge, - type BridgeConnection, type CookieField, type DisappearingTimerCapability, type GroupFieldCapability, diff --git a/src/resources/info.ts b/src/resources/info.ts index f405a629..263e7fed 100644 --- a/src/resources/info.ts +++ b/src/resources/info.ts @@ -12,7 +12,7 @@ export class BaseInfo extends APIResource { /** * Returns app, platform, server, endpoint discovery, OAuth, and WebSocket metadata - * for this Beeper Desktop instance. + * for this Beeper Client API server. */ retrieve(options?: RequestOptions): APIPromise { return this._client.get('/v1/info', { ...options, __security: {} }); @@ -123,7 +123,7 @@ export namespace InfoRetrieveResponse { export interface Server { /** - * Base URL of the Beeper Desktop API server + * Base URL of the Beeper Client API server */ base_url: string; diff --git a/src/resources/messages.ts b/src/resources/messages.ts index 607df984..3e034b47 100644 --- a/src/resources/messages.ts +++ b/src/resources/messages.ts @@ -23,7 +23,7 @@ export class BaseMessages extends APIResource { /** * Retrieve a message by final message ID, pendingMessageID, or Matrix event ID. - * Chat ID may be a Beeper chat ID or local chat ID. + * chatID may be a Beeper chat ID or a local chat ID. * * @example * ```ts @@ -153,21 +153,20 @@ export class Messages extends BaseMessages {} export interface MessageUpdateResponse extends Shared.Message { /** - * @deprecated DEPRECATED - use id instead. Compatibility alias for older clients. + * @deprecated Use id instead. */ messageID: string; /** - * @deprecated DEPRECATED - compatibility field. Successful responses are already - * represented by the 200 status code. + * @deprecated Use the HTTP 200 response status instead. */ success: true; } export interface MessageSendResponse { /** - * Chat ID. Input routes also accept the local chat ID from this Beeper Desktop - * installation when available. + * Chat ID. Input routes also accept the local chat ID from this installation when + * available. */ chatID: string; @@ -181,16 +180,16 @@ export interface MessageSendResponse { export interface MessageRetrieveParams { /** - * Chat ID. Input routes also accept the local chat ID from this Beeper Desktop - * installation when available. + * Chat ID. Input routes also accept the local chat ID from this installation when + * available. */ chatID: string; } export interface MessageUpdateParams { /** - * Path param: Chat ID. Input routes also accept the local chat ID from this Beeper - * Desktop installation when available. + * Path param: Chat ID. Input routes also accept the local chat ID from this + * installation when available. */ chatID: string; @@ -204,8 +203,8 @@ export interface MessageListParams extends CursorNoLimitParams {} export interface MessageDeleteParams { /** - * Path param: Chat ID. Input routes also accept the local chat ID from this Beeper - * Desktop installation when available. + * Path param: Chat ID. Input routes also accept the local chat ID from this + * installation when available. */ chatID: string; @@ -263,10 +262,10 @@ export interface MessageSearchParams extends CursorSearchParams { mediaTypes?: Array<'any' | 'video' | 'image' | 'link' | 'file'>; /** - * Literal word search (non-semantic). Finds messages containing these EXACT words - * in any order. Use single words users actually type, not concepts or phrases. - * Example: use "dinner" not "dinner plans", use "sick" not "health issues". If - * omitted, returns results filtered only by other parameters. + * Literal word search. Finds messages containing these words in any order. Use + * words the user actually typed, not inferred concepts. Example: use "dinner" + * rather than "dinner plans". If omitted, returns results filtered only by the + * other parameters. */ query?: string; @@ -289,8 +288,8 @@ export interface MessageSendParams { replyToMessageID?: string; /** - * Draft text. Plain text and Markdown are converted to Matrix HTML with the same - * rules used by send and edit. + * Draft text. Plain text and Markdown are converted to Beeper rich text with the + * same rules used by send and edit. */ text?: string; } diff --git a/src/resources/shared.ts b/src/resources/shared.ts index f5f34e6b..e431675c 100644 --- a/src/resources/shared.ts +++ b/src/resources/shared.ts @@ -17,7 +17,8 @@ export interface AppStateSnapshot { e2ee: AppStateSnapshot.E2EE; /** - * Current onboarding state for Beeper Desktop. + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. */ state: | 'needs-login' @@ -34,7 +35,7 @@ export interface AppStateSnapshot { matrix?: AppStateSnapshot.Matrix; /** - * Trusted-device verification progress. + * Trusted device verification progress. */ verification?: AppStateSnapshot.Verification; } @@ -132,7 +133,7 @@ export namespace AppStateSnapshot { deviceID: string; /** - * Beeper server URL for this account. + * Beeper homeserver URL for this account. */ homeserver: string; @@ -143,7 +144,7 @@ export namespace AppStateSnapshot { } /** - * Trusted-device verification progress. + * Trusted device verification progress. */ export interface Verification { /** @@ -187,7 +188,7 @@ export namespace AppStateSnapshot { otherDevice?: Verification.OtherDevice; /** - * Other user participating in verification. + * Other Beeper user participating in verification. */ otherUserID?: string; @@ -267,7 +268,7 @@ export interface Attachment { type: 'unknown' | 'img' | 'video' | 'audio'; /** - * Attachment identifier (typically an mxc:// URL). Use the download file endpoint + * Attachment identifier, typically an mxc:// URL. Use the download file endpoint * to get a local file path. */ id?: string; @@ -309,7 +310,7 @@ export interface Attachment { /** * Preview image URL for video attachments (poster frame). May be temporary or - * local-only to this device; download promptly if durable access is needed. + * available only on this device; download promptly if durable access is needed. */ posterImg?: string; @@ -319,8 +320,8 @@ export interface Attachment { size?: Attachment.Size; /** - * Public URL or local file path to fetch the file. May be temporary or local-only - * to this device; download promptly if durable access is needed. + * Public URL or local file path to fetch the file. May be temporary or available + * only on this device; download promptly if durable access is needed. */ srcURL?: string; @@ -421,14 +422,14 @@ export interface Message { accountID: string; /** - * Chat ID. Input routes also accept the local chat ID from this Beeper Desktop - * installation when available. + * Chat ID. Input routes also accept the local chat ID from this installation when + * available. */ chatID: string; /** - * Matrix-style fully-qualified sender user ID, usually including a bridge prefix - * and homeserver. + * Fully qualified sender user ID. Network-backed IDs usually include the network + * prefix and homeserver. */ senderID: string; @@ -499,7 +500,7 @@ export interface Message { seen?: boolean | string | { [key: string]: boolean | string }; /** - * Resolved sender display name (impersonator/full name/username/participant name). + * Resolved sender display name. */ senderName?: string; @@ -509,7 +510,7 @@ export interface Message { sendStatus?: Message.SendStatus; /** - * Matrix HTML body if present. + * Rich-text message body if present. */ text?: string; @@ -546,14 +547,14 @@ export namespace Message { url: string; /** - * Favicon URL if available. May be temporary or local-only to this device; + * Favicon URL if available. May be temporary or available only on this device; * download promptly if durable access is needed. */ favicon?: string; /** - * Preview image URL if available. May be temporary or local-only to this device; - * download promptly if durable access is needed. + * Preview image URL if available. May be temporary or available only on this + * device; download promptly if durable access is needed. */ img?: string; @@ -604,7 +605,8 @@ export namespace Message { deliveredToUsers?: Array; /** - * Internal bridge error detail. Intended for diagnostics, not end-user display. + * Diagnostic error detail from the messaging network adapter. Do not show directly + * to users. */ internalError?: string; @@ -645,7 +647,7 @@ export interface Reaction { emoji?: boolean; /** - * URL to the reaction's image. May be temporary or local-only to this device; + * URL to the reaction's image. May be temporary or available only on this device; * download promptly if durable access is needed. */ imgURL?: string; @@ -677,9 +679,9 @@ export interface User { fullName?: string; /** - * Avatar image URL if available. This may be a remote URL, Matrix media URL, data - * URL, or local filesystem URL depending on source and endpoint. May be temporary - * or local-only to this device; download promptly if durable access is needed. + * Avatar image URL if available. This may be a remote URL, media URL, data URL, or + * local file URL depending on the source. May be temporary or available only on + * this device; download promptly if durable access is needed. */ imgURL?: string; diff --git a/src/resources/top-level.ts b/src/resources/top-level.ts index 0cd89f42..a95fffae 100644 --- a/src/resources/top-level.ts +++ b/src/resources/top-level.ts @@ -72,7 +72,7 @@ export interface FocusParams { chatID?: string; /** - * Optional image path to populate in the message input field. + * Optional local image path to populate in the message input field. */ draftAttachmentPath?: string; @@ -89,7 +89,7 @@ export interface FocusParams { export interface SearchParams { /** - * User-typed search text. Literal word matching (non-semantic). + * User-typed search text. Uses literal word matching. */ query: string; } diff --git a/tests/api-resources/app/app.test.ts b/tests/api-resources/app/app.test.ts deleted file mode 100644 index d433c3b1..00000000 --- a/tests/api-resources/app/app.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { BaseApp } from '@beeper/desktop-api/resources/app/app'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseApp], -}); - -const runTests = (client: PartialBeeperDesktop<{ app: BaseApp }>) => { - test('session', async () => { - const responsePromise = client.app.session(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}; -describe('resource app', () => runTests(client)); -describe('resource app (tree shakable, base)', () => runTests(partialClient)); diff --git a/tests/api-resources/app/login/login.test.ts b/tests/api-resources/app/login/login.test.ts deleted file mode 100644 index 1e1492fe..00000000 --- a/tests/api-resources/app/login/login.test.ts +++ /dev/null @@ -1,95 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { App } from '@beeper/desktop-api/resources/app/app'; -import { BaseLogin } from '@beeper/desktop-api/resources/app/login/login'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseLogin], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [App], -}); - -const runTests = (client: PartialBeeperDesktop<{ app: { login: BaseLogin } }>) => { - test('email: only required params', async () => { - const responsePromise = client.app.login.email({ email: 'dev@stainless.com', request: 'request' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('email: required and optional params', async () => { - const response = await client.app.login.email({ email: 'dev@stainless.com', request: 'request' }); - }); - - test('register: only required params', async () => { - const responsePromise = client.app.login.register({ - acceptTerms: true, - leadToken: 'leadToken', - request: 'request', - username: 'x', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('register: required and optional params', async () => { - const response = await client.app.login.register({ - acceptTerms: true, - leadToken: 'leadToken', - request: 'request', - username: 'x', - }); - }); - - test('response: only required params', async () => { - const responsePromise = client.app.login.response({ request: 'request', response: 'response' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('response: required and optional params', async () => { - const response = await client.app.login.response({ request: 'request', response: 'response' }); - }); - - test('start', async () => { - const responsePromise = client.app.login.start(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}; -describe('resource login', () => runTests(client)); -describe('resource login (tree shakable, base)', () => runTests(partialClient)); -describe('resource login (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts b/tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts deleted file mode 100644 index e54a0559..00000000 --- a/tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts +++ /dev/null @@ -1,46 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Verification } from '@beeper/desktop-api/resources/app/login/verification/verification'; -import { BaseRecoveryKey } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/recovery-key'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseRecoveryKey], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Verification], -}); - -const runTests = ( - client: PartialBeeperDesktop<{ app: { login: { verification: { recoveryKey: BaseRecoveryKey } } } }>, -) => { - test('verify: only required params', async () => { - const responsePromise = client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('verify: required and optional params', async () => { - const response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' }); - }); -}; -describe('resource recoveryKey', () => runTests(client)); -describe('resource recoveryKey (tree shakable, base)', () => runTests(partialClient)); -describe('resource recoveryKey (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/login/verification/recovery-key/reset.test.ts b/tests/api-resources/app/login/verification/recovery-key/reset.test.ts deleted file mode 100644 index 178d978b..00000000 --- a/tests/api-resources/app/login/verification/recovery-key/reset.test.ts +++ /dev/null @@ -1,67 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { RecoveryKey } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/recovery-key'; -import { BaseReset } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/reset'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseReset], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [RecoveryKey], -}); - -const runTests = ( - client: PartialBeeperDesktop<{ app: { login: { verification: { recoveryKey: { reset: BaseReset } } } } }>, -) => { - test('create', async () => { - const responsePromise = client.app.login.verification.recoveryKey.reset.create(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.app.login.verification.recoveryKey.reset.create( - { existingRecoveryKey: 'existingRecoveryKey' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(BeeperDesktop.NotFoundError); - }); - - test('confirm: only required params', async () => { - const responsePromise = client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('confirm: required and optional params', async () => { - const response = await client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' }); - }); -}; -describe('resource reset', () => runTests(client)); -describe('resource reset (tree shakable, base)', () => runTests(partialClient)); -describe('resource reset (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/verifications/qr.test.ts b/tests/api-resources/app/verifications/qr.test.ts deleted file mode 100644 index fc09226d..00000000 --- a/tests/api-resources/app/verifications/qr.test.ts +++ /dev/null @@ -1,55 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { BaseQr } from '@beeper/desktop-api/resources/app/verifications/qr'; -import { Verifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseQr], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Verifications], -}); - -const runTests = (client: PartialBeeperDesktop<{ app: { verifications: { qr: BaseQr } } }>) => { - test('confirmScanned', async () => { - const responsePromise = client.app.verifications.qr.confirmScanned('x'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('scan: only required params', async () => { - const responsePromise = client.app.verifications.qr.scan({ data: 'x' }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('scan: required and optional params', async () => { - const response = await client.app.verifications.qr.scan({ data: 'x' }); - }); -}; -describe('resource qr', () => runTests(client)); -describe('resource qr (tree shakable, base)', () => runTests(partialClient)); -describe('resource qr (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/verifications/sas.test.ts b/tests/api-resources/app/verifications/sas.test.ts deleted file mode 100644 index 5564a785..00000000 --- a/tests/api-resources/app/verifications/sas.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { BaseSAS } from '@beeper/desktop-api/resources/app/verifications/sas'; -import { Verifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseSAS], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Verifications], -}); - -const runTests = (client: PartialBeeperDesktop<{ app: { verifications: { sas: BaseSAS } } }>) => { - test('confirm', async () => { - const responsePromise = client.app.verifications.sas.confirm('x'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('start', async () => { - const responsePromise = client.app.verifications.sas.start('x'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); -}; -describe('resource sas', () => runTests(client)); -describe('resource sas (tree shakable, base)', () => runTests(partialClient)); -describe('resource sas (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/verifications/verifications.test.ts b/tests/api-resources/app/verifications/verifications.test.ts deleted file mode 100644 index 076b9daf..00000000 --- a/tests/api-resources/app/verifications/verifications.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { App } from '@beeper/desktop-api/resources/app/app'; -import { BaseVerifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseVerifications], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [App], -}); - -const runTests = (client: PartialBeeperDesktop<{ app: { verifications: BaseVerifications } }>) => { - test('create', async () => { - const responsePromise = client.app.verifications.create(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('create: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.app.verifications.create( - { purpose: 'login', userID: 'userID' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(BeeperDesktop.NotFoundError); - }); - - test('retrieve', async () => { - const responsePromise = client.app.verifications.retrieve('x'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('list', async () => { - const responsePromise = client.app.verifications.list(); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('accept', async () => { - const responsePromise = client.app.verifications.accept('x'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('cancel', async () => { - const responsePromise = client.app.verifications.cancel('x'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('cancel: request options and params are passed correctly', async () => { - // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error - await expect( - client.app.verifications.cancel( - 'x', - { code: 'code', reason: 'reason' }, - { path: '/_stainless_unknown_path' }, - ), - ).rejects.toThrow(BeeperDesktop.NotFoundError); - }); -}; -describe('resource verifications', () => runTests(client)); -describe('resource verifications (tree shakable, base)', () => runTests(partialClient)); -describe('resource verifications (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/bridges/connections.test.ts b/tests/api-resources/bridges/connections.test.ts deleted file mode 100644 index f08aaa25..00000000 --- a/tests/api-resources/bridges/connections.test.ts +++ /dev/null @@ -1,80 +0,0 @@ -// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -import { Bridges } from '@beeper/desktop-api/resources/bridges/bridges'; -import { BaseConnections } from '@beeper/desktop-api/resources/bridges/connections'; - -import BeeperDesktop from '@beeper/desktop-api'; -import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; - -const client = new BeeperDesktop({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); - -const partialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [BaseConnections], -}); - -const parentPartialClient = createClient({ - accessToken: 'My Access Token', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - resources: [Bridges], -}); - -const runTests = (client: PartialBeeperDesktop<{ bridges: { connections: BaseConnections } }>) => { - test('retrieve: only required params', async () => { - const responsePromise = client.bridges.connections.retrieve('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { - bridgeID: 'local-whatsapp', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('retrieve: required and optional params', async () => { - const response = await client.bridges.connections.retrieve('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { - bridgeID: 'local-whatsapp', - }); - }); - - test('list', async () => { - const responsePromise = client.bridges.connections.list('local-whatsapp'); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('remove: only required params', async () => { - const responsePromise = client.bridges.connections.remove('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { - bridgeID: 'local-whatsapp', - scope: 'current-device', - }); - const rawResponse = await responsePromise.asResponse(); - expect(rawResponse).toBeInstanceOf(Response); - const response = await responsePromise; - expect(response).not.toBeInstanceOf(Response); - const dataAndResponse = await responsePromise.withResponse(); - expect(dataAndResponse.data).toBe(response); - expect(dataAndResponse.response).toBe(rawResponse); - }); - - test('remove: required and optional params', async () => { - const response = await client.bridges.connections.remove('ba_EvYDBBsZbRQAy3UOSWqG0LuTVkc', { - bridgeID: 'local-whatsapp', - scope: 'current-device', - }); - }); -}; -describe('resource connections', () => runTests(client)); -describe('resource connections (tree shakable, base)', () => runTests(partialClient)); -describe('resource connections (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/bridges/login-sessions/login-sessions.test.ts b/tests/api-resources/bridges/login-sessions/login-sessions.test.ts index d0759efd..28d5de25 100644 --- a/tests/api-resources/bridges/login-sessions/login-sessions.test.ts +++ b/tests/api-resources/bridges/login-sessions/login-sessions.test.ts @@ -41,9 +41,9 @@ const runTests = (client: PartialBeeperDesktop<{ bridges: { loginSessions: BaseL client.bridges.loginSessions.create( 'local-whatsapp', { - accountID: 'accountID', - flowID: 'flowID', - loginID: 'loginID', + accountID: 'x', + flowID: 'x', + loginID: 'x', }, { path: '/_stainless_unknown_path' }, ), From b9c1714410139c2139b597338cd002d785653e85 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 17 May 2026 16:35:45 +0000 Subject: [PATCH 12/17] feat(api): add login flow, verifications, recovery key methods to app --- .stats.yml | 6 +- api.md | 72 + packages/mcp-server/src/code-tool-worker.ts | 17 + packages/mcp-server/src/local-docs-search.ts | 759 +++++++ packages/mcp-server/src/methods.ts | 102 + src/client.ts | 4 +- src/resources/app/app.ts | 310 ++- src/resources/app/index.ts | 25 +- src/resources/app/login/index.ts | 11 +- src/resources/app/login/login.ts | 761 ++++++- src/resources/app/login/verification/index.ts | 7 +- .../login/verification/recovery-key/index.ts | 16 +- .../verification/recovery-key/recovery-key.ts | 308 ++- .../login/verification/recovery-key/reset.ts | 581 ++++++ .../app/login/verification/verification.ts | 14 +- src/resources/app/verifications/index.ts | 16 +- src/resources/app/verifications/qr.ts | 808 ++++++++ src/resources/app/verifications/sas.ts | 797 ++++++++ .../app/verifications/verifications.ts | 1769 ++++++++++++++++- src/resources/index.ts | 2 +- tests/api-resources/app/app.test.ts | 32 + tests/api-resources/app/login/login.test.ts | 107 + .../recovery-key/recovery-key.test.ts | 46 + .../verification/recovery-key/reset.test.ts | 67 + .../app/verifications/qr.test.ts | 55 + .../app/verifications/sas.test.ts | 51 + .../app/verifications/verifications.test.ts | 105 + 27 files changed, 6814 insertions(+), 34 deletions(-) create mode 100644 tests/api-resources/app/app.test.ts create mode 100644 tests/api-resources/app/login/login.test.ts create mode 100644 tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts create mode 100644 tests/api-resources/app/login/verification/recovery-key/reset.test.ts create mode 100644 tests/api-resources/app/verifications/qr.test.ts create mode 100644 tests/api-resources/app/verifications/sas.test.ts create mode 100644 tests/api-resources/app/verifications/verifications.test.ts diff --git a/.stats.yml b/.stats.yml index f8d62378..3e06ccc4 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 39 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-87df69f641d994f09669f77093988df0b13da380d36076964d4a2563e9ce202e.yml +configured_endpoints: 56 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper/beeper-desktop-api-baac187842e51587134950c59c4d746bfcb59239f01919ed83b92c24c47d98f4.yml openapi_spec_hash: 9de80d05f7562b7ecd07c466f0fdf58b -config_hash: 2ebcc80e2cbd2342e132f4474ec24212 +config_hash: a8a4a8b869ccd5976fd4107e67d2ecae diff --git a/api.md b/api.md index 7537ea0b..5c996b91 100644 --- a/api.md +++ b/api.md @@ -189,17 +189,89 @@ Methods: Types: - Verification +- AppSessionResponse + +Methods: + +- client.app.session() -> AppSessionResponse ## Login +Types: + +- LoginRegisterResponse +- LoginResponseResponse +- LoginStartResponse + +Methods: + +- client.app.login.email({ ...params }) -> void +- client.app.login.register({ ...params }) -> LoginRegisterResponse +- client.app.login.response({ ...params }) -> LoginResponseResponse +- client.app.login.start() -> LoginStartResponse + ### Verification #### RecoveryKey +Types: + +- RecoveryKeyVerifyResponse + +Methods: + +- client.app.login.verification.recoveryKey.verify({ ...params }) -> RecoveryKeyVerifyResponse + ##### Reset +Types: + +- ResetCreateResponse +- ResetConfirmResponse + +Methods: + +- client.app.login.verification.recoveryKey.reset.create({ ...params }) -> ResetCreateResponse +- client.app.login.verification.recoveryKey.reset.confirm({ ...params }) -> ResetConfirmResponse + ## Verifications +Types: + +- VerificationCreateResponse +- VerificationRetrieveResponse +- VerificationListResponse +- VerificationAcceptResponse +- VerificationCancelResponse + +Methods: + +- client.app.verifications.create({ ...params }) -> VerificationCreateResponse +- client.app.verifications.retrieve(verificationID) -> VerificationRetrieveResponse +- client.app.verifications.list() -> VerificationListResponse +- client.app.verifications.accept(verificationID) -> VerificationAcceptResponse +- client.app.verifications.cancel(verificationID, { ...params }) -> VerificationCancelResponse + ### Qr +Types: + +- QrConfirmScannedResponse +- QrScanResponse + +Methods: + +- client.app.verifications.qr.confirmScanned(verificationID) -> QrConfirmScannedResponse +- client.app.verifications.qr.scan({ ...params }) -> QrScanResponse + ### SAS + +Types: + +- SASConfirmResponse +- SASStartResponse + +Methods: + +- client.app.verifications.sas.confirm(verificationID) -> SASConfirmResponse +- client.app.verifications.sas.start(verificationID) -> SASStartResponse diff --git a/packages/mcp-server/src/code-tool-worker.ts b/packages/mcp-server/src/code-tool-worker.ts index 8005afd0..931835fa 100644 --- a/packages/mcp-server/src/code-tool-worker.ts +++ b/packages/mcp-server/src/code-tool-worker.ts @@ -147,6 +147,23 @@ const fuse = new Fuse( 'client.assets.upload', 'client.assets.uploadBase64', 'client.info.retrieve', + 'client.app.session', + 'client.app.login.email', + 'client.app.login.register', + 'client.app.login.response', + 'client.app.login.start', + 'client.app.login.verification.recoveryKey.verify', + 'client.app.login.verification.recoveryKey.reset.confirm', + 'client.app.login.verification.recoveryKey.reset.create', + 'client.app.verifications.accept', + 'client.app.verifications.cancel', + 'client.app.verifications.create', + 'client.app.verifications.list', + 'client.app.verifications.retrieve', + 'client.app.verifications.qr.confirmScanned', + 'client.app.verifications.qr.scan', + 'client.app.verifications.sas.confirm', + 'client.app.verifications.sas.start', ], { threshold: 1, shouldSort: true }, ); diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 1ccd7fed..ed60808a 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -1872,6 +1872,765 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, }, }, + { + name: 'session', + endpoint: '/v1/app/setup', + httpMethod: 'get', + summary: 'Get Beeper app setup state', + description: + 'Return the current Beeper Desktop or Beeper Server sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that sign-in is needed; after sign-in, pass a read token.', + stainlessPath: '(resource) app > (method) session', + qualified: 'client.app.session', + response: + "{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }", + markdown: + "## session\n\n`client.app.session(): { e2ee: object; state: string; matrix?: object; verification?: object; }`\n\n**get** `/v1/app/setup`\n\nReturn the current Beeper Desktop or Beeper Server sign-in and encrypted messaging setup state. This endpoint is public before sign-in so apps can discover that sign-in is needed; after sign-in, pass a read token.\n\n### Returns\n\n- `{ e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }`\n - `state: string`\n - `matrix?: { deviceID: string; homeserver: string; userID: string; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.session();\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.session', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.session();\n\nconsole.log(response.e2ee);", + }, + python: { + method: 'app.session', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.session()\nprint(response.e2ee)', + }, + go: { + method: 'client.App.Session', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Session(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.E2EE)\n}\n', + }, + cli: { + method: 'app session', + example: "beeper-desktop app session \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->session', + example: + "app->session();\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'start', + endpoint: '/v1/app/setup/start', + httpMethod: 'post', + summary: 'Start Beeper app setup', + description: + 'Start setting up Beeper Desktop or Beeper Server. The flow supports existing Beeper accounts and new account creation.', + stainlessPath: '(resource) app.login > (method) start', + qualified: 'client.app.login.start', + response: '{ setupRequestID: string; signInMethods: string[]; }', + markdown: + "## start\n\n`client.app.login.start(): { setupRequestID: string; signInMethods: string[]; }`\n\n**post** `/v1/app/setup/start`\n\nStart setting up Beeper Desktop or Beeper Server. The flow supports existing Beeper accounts and new account creation.\n\n### Returns\n\n- `{ setupRequestID: string; signInMethods: string[]; }`\n\n - `setupRequestID: string`\n - `signInMethods: string[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.start', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.start();\n\nconsole.log(response.setupRequestID);", + }, + python: { + method: 'app.login.start', + example: + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.start()\nprint(response.setup_request_id)', + }, + go: { + method: 'client.App.Login.Start', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Start(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.SetupRequestID)\n}\n', + }, + cli: { + method: 'login start', + example: "beeper-desktop app:login start \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->login->start', + example: + "app->login->start();\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'email', + endpoint: '/v1/app/setup/email', + httpMethod: 'post', + summary: 'Send setup sign-in code', + description: 'Send a sign-in code to the user email address for app setup.', + stainlessPath: '(resource) app.login > (method) email', + qualified: 'client.app.login.email', + params: ['email: string;', 'setupRequestID: string;'], + markdown: + "## email\n\n`client.app.login.email(email: string, setupRequestID: string): void`\n\n**post** `/v1/app/setup/email`\n\nSend a sign-in code to the user email address for app setup.\n\n### Parameters\n\n- `email: string`\n Email address to send the sign-in code to.\n\n- `setupRequestID: string`\n Setup request ID returned by the start step.\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.app.login.email({ email: 'dev@stainless.com', setupRequestID: 'setupRequestID' })\n```", + perLanguage: { + typescript: { + method: 'client.app.login.email', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nawait client.app.login.email({ email: 'dev@stainless.com', setupRequestID: 'setupRequestID' });", + }, + python: { + method: 'app.login.email', + example: + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nclient.app.login.email(\n email="dev@stainless.com",\n setup_request_id="setupRequestID",\n)', + }, + go: { + method: 'client.App.Login.Email', + example: + 'package main\n\nimport (\n\t"context"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\terr := client.App.Login.Email(context.TODO(), beeperdesktopapi.AppLoginEmailParams{\n\t\tEmail: "dev@stainless.com",\n\t\tSetupRequestID: "setupRequestID",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n}\n', + }, + cli: { + method: 'login email', + example: + "beeper-desktop app:login email \\\n --access-token 'My Access Token' \\\n --email dev@stainless.com \\\n --setup-request-id setupRequestID", + }, + php: { + method: 'app->login->email', + example: + "app->login->email(\n email: 'dev@stainless.com', setupRequestID: 'setupRequestID'\n);\n\nvar_dump($result);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/email \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "email": "dev@stainless.com",\n "setupRequestID": "setupRequestID"\n }\'', + }, + }, + }, + { + name: 'response', + endpoint: '/v1/app/setup/response', + httpMethod: 'post', + summary: 'Complete setup sign-in with code', + description: + 'Finish setup sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.', + stainlessPath: '(resource) app.login > (method) response', + qualified: 'client.app.login.response', + params: ['response: string;', 'setupRequestID: string;'], + response: + "{ matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; setupRequestID: string; usernameSuggestions?: string[]; }", + markdown: + "## response\n\n`client.app.login.response(response: string, setupRequestID: string): { matrix: object; session: object; } | { copy: object; leadToken: string; registrationRequired: true; setupRequestID: string; usernameSuggestions?: string[]; }`\n\n**post** `/v1/app/setup/response`\n\nFinish setup sign-in with the code sent to the user email address. If the user needs a new account, the response includes account creation copy and username suggestions.\n\n### Parameters\n\n- `response: string`\n Sign-in code from the user email.\n\n- `setupRequestID: string`\n Setup request ID returned by the start step.\n\n### Returns\n\n- `{ matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; } | { copy: { submit: 'Continue'; terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; title: 'Choose your username'; usernamePlaceholder: 'Username'; }; leadToken: string; registrationRequired: true; setupRequestID: string; usernameSuggestions?: string[]; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({ response: 'response', setupRequestID: 'setupRequestID' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.response', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.response({\n response: 'response',\n setupRequestID: 'setupRequestID',\n});\n\nconsole.log(response);", + }, + python: { + method: 'app.login.response', + example: + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.response(\n response="response",\n setup_request_id="setupRequestID",\n)\nprint(response)', + }, + go: { + method: 'client.App.Login.Response', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Response(context.TODO(), beeperdesktopapi.AppLoginResponseParams{\n\t\tResponse: "response",\n\t\tSetupRequestID: "setupRequestID",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response)\n}\n', + }, + cli: { + method: 'login response', + example: + "beeper-desktop app:login response \\\n --access-token 'My Access Token' \\\n --response response \\\n --setup-request-id setupRequestID", + }, + php: { + method: 'app->login->response', + example: + "app->login->response(\n response: 'response', setupRequestID: 'setupRequestID'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/response \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "response": "response",\n "setupRequestID": "setupRequestID"\n }\'', + }, + }, + }, + { + name: 'register', + endpoint: '/v1/app/setup/register', + httpMethod: 'post', + summary: 'Create account for setup', + description: 'Create a Beeper account after the user chooses a username and accepts the Terms of Use.', + stainlessPath: '(resource) app.login > (method) register', + qualified: 'client.app.login.register', + params: ['acceptTerms: true;', 'leadToken: string;', 'setupRequestID: string;', 'username: string;'], + response: + "{ matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", + markdown: + "## register\n\n`client.app.login.register(acceptTerms: true, leadToken: string, setupRequestID: string, username: string): { matrix: object; session: object; }`\n\n**post** `/v1/app/setup/register`\n\nCreate a Beeper account after the user chooses a username and accepts the Terms of Use.\n\n### Parameters\n\n- `acceptTerms: true`\n Confirms that the user agreed to our [terms of use](https://www.beeper.com/terms-onboarding) and has read our [privacy policy](https://www.beeper.com/privacy).\n\n- `leadToken: string`\n Registration token returned by Beeper.\n\n- `setupRequestID: string`\n Setup request ID returned by the start step.\n\n- `username: string`\n Username selected by the user.\n\n### Returns\n\n- `{ matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `matrix: { accessToken: string; deviceID: string; homeserver: string; userID: string; }`\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n setupRequestID: 'setupRequestID',\n username: 'x',\n});\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.register', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.register({\n acceptTerms: true,\n leadToken: 'leadToken',\n setupRequestID: 'setupRequestID',\n username: 'x',\n});\n\nconsole.log(response.matrix);", + }, + python: { + method: 'app.login.register', + example: + 'from beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop()\nresponse = client.app.login.register(\n accept_terms=True,\n lead_token="leadToken",\n setup_request_id="setupRequestID",\n username="x",\n)\nprint(response.matrix)', + }, + go: { + method: 'client.App.Login.Register', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Register(context.TODO(), beeperdesktopapi.AppLoginRegisterParams{\n\t\tAcceptTerms: true,\n\t\tLeadToken: "leadToken",\n\t\tSetupRequestID: "setupRequestID",\n\t\tUsername: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Matrix)\n}\n', + }, + cli: { + method: 'login register', + example: + "beeper-desktop app:login register \\\n --access-token 'My Access Token' \\\n --accept-terms true \\\n --lead-token leadToken \\\n --setup-request-id setupRequestID \\\n --username x", + }, + php: { + method: 'app->login->register', + example: + "app->login->register(\n acceptTerms: true,\n leadToken: 'leadToken',\n setupRequestID: 'setupRequestID',\n username: 'x',\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/register \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "acceptTerms": true,\n "leadToken": "leadToken",\n "setupRequestID": "setupRequestID",\n "username": "x"\n }\'', + }, + }, + }, + { + name: 'verify', + endpoint: '/v1/app/setup/verification/recovery-key', + httpMethod: 'post', + summary: 'Verify with recovery key', + description: 'Unlock encrypted messages with the user recovery key.', + stainlessPath: '(resource) app.login.verification.recovery_key > (method) verify', + qualified: 'client.app.login.verification.recoveryKey.verify', + params: ['recoveryKey: string;'], + response: + "{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", + markdown: + "## verify\n\n`client.app.login.verification.recoveryKey.verify(recoveryKey: string): { session: object; }`\n\n**post** `/v1/app/setup/verification/recovery-key`\n\nUnlock encrypted messages with the user recovery key.\n\n### Parameters\n\n- `recoveryKey: string`\n Recovery key saved by the user.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.verification.recoveryKey.verify', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' });\n\nconsole.log(response.session);", + }, + python: { + method: 'app.login.verification.recovery_key.verify', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.login.verification.recovery_key.verify(\n recovery_key="x",\n)\nprint(response.session)', + }, + go: { + method: 'client.App.Login.Verification.RecoveryKey.Verify', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Verification.RecoveryKey.Verify(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyVerifyParams{\n\t\tRecoveryKey: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', + }, + cli: { + method: 'recovery_key verify', + example: + "beeper-desktop app:login:verification:recovery-key verify \\\n --access-token 'My Access Token' \\\n --recovery-key x", + }, + php: { + method: 'app->login->verification->recoveryKey->verify', + example: + "app->login->verification->recoveryKey->verify(\n recoveryKey: 'x'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verification/recovery-key \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryKey": "x"\n }\'', + }, + }, + }, + { + name: 'create', + endpoint: '/v1/app/setup/verification/recovery-key/reset', + httpMethod: 'post', + summary: 'Create new recovery key', + description: 'Create a new recovery key when the user cannot use the existing one.', + stainlessPath: '(resource) app.login.verification.recovery_key.reset > (method) create', + qualified: 'client.app.login.verification.recoveryKey.reset.create', + params: ['existingRecoveryKey?: string;'], + response: + "{ recoveryKey: string; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", + markdown: + "## create\n\n`client.app.login.verification.recoveryKey.reset.create(existingRecoveryKey?: string): { recoveryKey: string; session: object; }`\n\n**post** `/v1/app/setup/verification/recovery-key/reset`\n\nCreate a new recovery key when the user cannot use the existing one.\n\n### Parameters\n\n- `existingRecoveryKey?: string`\n Existing recovery key, if the user has it.\n\n### Returns\n\n- `{ recoveryKey: string; session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `recoveryKey: string`\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst reset = await client.app.login.verification.recoveryKey.reset.create();\n\nconsole.log(reset);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.verification.recoveryKey.reset.create', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst reset = await client.app.login.verification.recoveryKey.reset.create();\n\nconsole.log(reset.recoveryKey);", + }, + python: { + method: 'app.login.verification.recovery_key.reset.create', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nreset = client.app.login.verification.recovery_key.reset.create()\nprint(reset.recovery_key)', + }, + go: { + method: 'client.App.Login.Verification.RecoveryKey.Reset.New', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\treset, err := client.App.Login.Verification.RecoveryKey.Reset.New(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyResetNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", reset.RecoveryKey)\n}\n', + }, + cli: { + method: 'reset create', + example: + "beeper-desktop app:login:verification:recovery-key:reset create \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->login->verification->recoveryKey->reset->create', + example: + "app->login->verification->recoveryKey->reset->create(\n existingRecoveryKey: 'existingRecoveryKey'\n);\n\nvar_dump($reset);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verification/recovery-key/reset \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'confirm', + endpoint: '/v1/app/setup/verification/recovery-key/reset/confirm', + httpMethod: 'post', + summary: 'Confirm new recovery key', + description: 'Confirm that the new recovery key should be used for this account.', + stainlessPath: '(resource) app.login.verification.recovery_key.reset > (method) confirm', + qualified: 'client.app.login.verification.recoveryKey.reset.confirm', + params: ['recoveryKey: string;'], + response: + "{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }", + markdown: + "## confirm\n\n`client.app.login.verification.recoveryKey.reset.confirm(recoveryKey: string): { session: object; }`\n\n**post** `/v1/app/setup/verification/recovery-key/reset/confirm`\n\nConfirm that the new recovery key should be used for this account.\n\n### Parameters\n\n- `recoveryKey: string`\n New recovery key returned by the reset step.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.login.verification.recoveryKey.reset.confirm', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.login.verification.recoveryKey.reset.confirm({\n recoveryKey: 'x',\n});\n\nconsole.log(response.session);", + }, + python: { + method: 'app.login.verification.recovery_key.reset.confirm', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.login.verification.recovery_key.reset.confirm(\n recovery_key="x",\n)\nprint(response.session)', + }, + go: { + method: 'client.App.Login.Verification.RecoveryKey.Reset.Confirm', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Login.Verification.RecoveryKey.Reset.Confirm(context.TODO(), beeperdesktopapi.AppLoginVerificationRecoveryKeyResetConfirmParams{\n\t\tRecoveryKey: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', + }, + cli: { + method: 'reset confirm', + example: + "beeper-desktop app:login:verification:recovery-key:reset confirm \\\n --access-token 'My Access Token' \\\n --recovery-key x", + }, + php: { + method: 'app->login->verification->recoveryKey->reset->confirm', + example: + "app->login->verification->recoveryKey->reset->confirm(\n recoveryKey: 'x'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verification/recovery-key/reset/confirm \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "recoveryKey": "x"\n }\'', + }, + }, + }, + { + name: 'list', + endpoint: '/v1/app/setup/verifications', + httpMethod: 'get', + summary: 'List active verifications', + description: + 'List pending and active device verifications. Use this to recover state without a WebSocket connection.', + stainlessPath: '(resource) app.verifications > (method) list', + qualified: 'client.app.verifications.list', + response: + "{ items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]; }", + markdown: + "## list\n\n`client.app.verifications.list(): { items: object[]; }`\n\n**get** `/v1/app/setup/verifications`\n\nList pending and active device verifications. Use this to recover state without a WebSocket connection.\n\n### Returns\n\n- `{ items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]; }`\n\n - `items: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }[]`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verifications = await client.app.verifications.list();\n\nconsole.log(verifications);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.list', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verifications = await client.app.verifications.list();\n\nconsole.log(verifications.items);", + }, + python: { + method: 'app.verifications.list', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverifications = client.app.verifications.list()\nprint(verifications.items)', + }, + go: { + method: 'client.App.Verifications.List', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverifications, err := client.App.Verifications.List(context.TODO())\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verifications.Items)\n}\n', + }, + cli: { + method: 'verifications list', + example: "beeper-desktop app:verifications list \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->verifications->list', + example: + "app->verifications->list();\n\nvar_dump($verifications);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'create', + endpoint: '/v1/app/setup/verifications', + httpMethod: 'post', + summary: 'Start device verification', + description: 'Start verifying this device from another signed-in device.', + stainlessPath: '(resource) app.verifications > (method) create', + qualified: 'client.app.verifications.create', + params: ["purpose?: 'login' | 'device';", 'userID?: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", + markdown: + "## create\n\n`client.app.verifications.create(purpose?: 'login' | 'device', userID?: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/setup/verifications`\n\nStart verifying this device from another signed-in device.\n\n### Parameters\n\n- `purpose?: 'login' | 'device'`\n Why this verification is being started.\n\n- `userID?: string`\n Beeper user ID to verify. Defaults to the signed-in user.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.verifications.create();\n\nconsole.log(verification);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.create', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.verifications.create();\n\nconsole.log(verification.session);", + }, + python: { + method: 'app.verifications.create', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.verifications.create()\nprint(verification.session)', + }, + go: { + method: 'client.App.Verifications.New', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.Verifications.New(context.TODO(), beeperdesktopapi.AppVerificationNewParams{})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.Session)\n}\n', + }, + cli: { + method: 'verifications create', + example: "beeper-desktop app:verifications create \\\n --access-token 'My Access Token'", + }, + php: { + method: 'app->verifications->create', + example: + "app->verifications->create(\n purpose: 'login', userID: 'userID'\n);\n\nvar_dump($verification);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'retrieve', + endpoint: '/v1/app/setup/verifications/{verificationID}', + httpMethod: 'get', + summary: 'Get verification', + description: 'Get the current state of a device verification transaction.', + stainlessPath: '(resource) app.verifications > (method) retrieve', + qualified: 'client.app.verifications.retrieve', + params: ['verificationID: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", + markdown: + "## retrieve\n\n`client.app.verifications.retrieve(verificationID: string): { session: object; verification?: object; }`\n\n**get** `/v1/app/setup/verifications/{verificationID}`\n\nGet the current state of a device verification transaction.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst verification = await client.app.verifications.retrieve('x');\n\nconsole.log(verification);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.retrieve', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst verification = await client.app.verifications.retrieve('x');\n\nconsole.log(verification.session);", + }, + python: { + method: 'app.verifications.retrieve', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nverification = client.app.verifications.retrieve(\n "x",\n)\nprint(verification.session)', + }, + go: { + method: 'client.App.Verifications.Get', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tverification, err := client.App.Verifications.Get(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", verification.Session)\n}\n', + }, + cli: { + method: 'verifications retrieve', + example: + "beeper-desktop app:verifications retrieve \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->verifications->retrieve', + example: + "app->verifications->retrieve('x');\n\nvar_dump($verification);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications/$VERIFICATION_ID \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'accept', + endpoint: '/v1/app/setup/verifications/{verificationID}/accept', + httpMethod: 'post', + summary: 'Accept device verification', + description: 'Accept an incoming device verification request.', + stainlessPath: '(resource) app.verifications > (method) accept', + qualified: 'client.app.verifications.accept', + params: ['verificationID: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", + markdown: + "## accept\n\n`client.app.verifications.accept(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/setup/verifications/{verificationID}/accept`\n\nAccept an incoming device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.accept('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.accept', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.accept('x');\n\nconsole.log(response.session);", + }, + python: { + method: 'app.verifications.accept', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.accept(\n "x",\n)\nprint(response.session)', + }, + go: { + method: 'client.App.Verifications.Accept', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Accept(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', + }, + cli: { + method: 'verifications accept', + example: + "beeper-desktop app:verifications accept \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->verifications->accept', + example: + "app->verifications->accept('x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications/$VERIFICATION_ID/accept \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'cancel', + endpoint: '/v1/app/setup/verifications/{verificationID}/cancel', + httpMethod: 'post', + summary: 'Cancel device verification', + description: 'Cancel an active device verification request.', + stainlessPath: '(resource) app.verifications > (method) cancel', + qualified: 'client.app.verifications.cancel', + params: ['verificationID: string;', 'code?: string;', 'reason?: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", + markdown: + "## cancel\n\n`client.app.verifications.cancel(verificationID: string, code?: string, reason?: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/setup/verifications/{verificationID}/cancel`\n\nCancel an active device verification request.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n- `code?: string`\n Optional cancellation code.\n\n- `reason?: string`\n Optional user-facing cancellation reason.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.cancel('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.cancel', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.cancel('x');\n\nconsole.log(response.session);", + }, + python: { + method: 'app.verifications.cancel', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.cancel(\n verification_id="x",\n)\nprint(response.session)', + }, + go: { + method: 'client.App.Verifications.Cancel', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Cancel(\n\t\tcontext.TODO(),\n\t\t"x",\n\t\tbeeperdesktopapi.AppVerificationCancelParams{},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', + }, + cli: { + method: 'verifications cancel', + example: + "beeper-desktop app:verifications cancel \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->verifications->cancel', + example: + "app->verifications->cancel(\n 'x', code: 'code', reason: 'reason'\n);\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications/$VERIFICATION_ID/cancel \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'scan', + endpoint: '/v1/app/setup/verifications/qr/scan', + httpMethod: 'post', + summary: 'Scan verification QR code', + description: 'Submit the QR code scanned from another signed-in device.', + stainlessPath: '(resource) app.verifications.qr > (method) scan', + qualified: 'client.app.verifications.qr.scan', + params: ['data: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", + markdown: + "## scan\n\n`client.app.verifications.qr.scan(data: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/setup/verifications/qr/scan`\n\nSubmit the QR code scanned from another signed-in device.\n\n### Parameters\n\n- `data: string`\n QR code payload scanned from the other device.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.qr.scan({ data: 'x' });\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.qr.scan', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.qr.scan({ data: 'x' });\n\nconsole.log(response.session);", + }, + python: { + method: 'app.verifications.qr.scan', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.qr.scan(\n data="x",\n)\nprint(response.session)', + }, + go: { + method: 'client.App.Verifications.Qr.Scan', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Qr.Scan(context.TODO(), beeperdesktopapi.AppVerificationQrScanParams{\n\t\tData: "x",\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', + }, + cli: { + method: 'qr scan', + example: + "beeper-desktop app:verifications:qr scan \\\n --access-token 'My Access Token' \\\n --data x", + }, + php: { + method: 'app->verifications->qr->scan', + example: + "app->verifications->qr->scan(data: 'x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications/qr/scan \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN" \\\n -d \'{\n "data": "x"\n }\'', + }, + }, + }, + { + name: 'confirm_scanned', + endpoint: '/v1/app/setup/verifications/{verificationID}/qr/confirm-scanned', + httpMethod: 'post', + summary: 'Confirm QR code scan', + description: 'Confirm that another device scanned this device QR code.', + stainlessPath: '(resource) app.verifications.qr > (method) confirm_scanned', + qualified: 'client.app.verifications.qr.confirmScanned', + params: ['verificationID: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", + markdown: + "## confirm_scanned\n\n`client.app.verifications.qr.confirmScanned(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/setup/verifications/{verificationID}/qr/confirm-scanned`\n\nConfirm that another device scanned this device QR code.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.qr.confirmScanned('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.qr.confirmScanned', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.qr.confirmScanned('x');\n\nconsole.log(response.session);", + }, + python: { + method: 'app.verifications.qr.confirm_scanned', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.qr.confirm_scanned(\n "x",\n)\nprint(response.session)', + }, + go: { + method: 'client.App.Verifications.Qr.ConfirmScanned', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.Qr.ConfirmScanned(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', + }, + cli: { + method: 'qr confirm_scanned', + example: + "beeper-desktop app:verifications:qr confirm-scanned \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->verifications->qr->confirmScanned', + example: + "app->verifications->qr->confirmScanned('x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications/$VERIFICATION_ID/qr/confirm-scanned \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'start', + endpoint: '/v1/app/setup/verifications/{verificationID}/sas/start', + httpMethod: 'post', + summary: 'Start emoji verification', + description: 'Start emoji comparison for device verification.', + stainlessPath: '(resource) app.verifications.sas > (method) start', + qualified: 'client.app.verifications.sas.start', + params: ['verificationID: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", + markdown: + "## start\n\n`client.app.verifications.sas.start(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/setup/verifications/{verificationID}/sas/start`\n\nStart emoji comparison for device verification.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.sas.start('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.sas.start', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.sas.start('x');\n\nconsole.log(response.session);", + }, + python: { + method: 'app.verifications.sas.start', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.sas.start(\n "x",\n)\nprint(response.session)', + }, + go: { + method: 'client.App.Verifications.SAS.Start', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.SAS.Start(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', + }, + cli: { + method: 'sas start', + example: + "beeper-desktop app:verifications:sas start \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->verifications->sas->start', + example: + "app->verifications->sas->start('x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications/$VERIFICATION_ID/sas/start \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, + { + name: 'confirm', + endpoint: '/v1/app/setup/verifications/{verificationID}/sas/confirm', + httpMethod: 'post', + summary: 'Confirm emoji verification', + description: 'Confirm that the emoji or number sequence matches on both devices.', + stainlessPath: '(resource) app.verifications.sas > (method) confirm', + qualified: 'client.app.verifications.sas.confirm', + params: ['verificationID: string;'], + response: + "{ session: { e2ee: object; state: string; matrix?: object; verification?: object; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }", + markdown: + "## confirm\n\n`client.app.verifications.sas.confirm(verificationID: string): { session: object; verification?: object; }`\n\n**post** `/v1/app/setup/verifications/{verificationID}/sas/confirm`\n\nConfirm that the emoji or number sequence matches on both devices.\n\n### Parameters\n\n- `verificationID: string`\n Verification ID.\n\n### Returns\n\n- `{ session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: object; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: object; otherDevice?: object; otherUserID?: string; qr?: object; sas?: object; }; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n\n - `session: { e2ee: { crossSigning: boolean; firstSyncDone: boolean; hasBackedUpRecoveryKey: boolean; initialized: boolean; keyBackup: boolean; secrets: { masterKey: boolean; megolmBackupKey: boolean; recoveryKey: boolean; selfSigningKey: boolean; userSigningKey: boolean; }; secretStorage: boolean; verified: boolean; recoveryKeyGeneratedAt?: number; }; state: string; matrix?: { deviceID: string; homeserver: string; userID: string; }; verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }; }`\n - `verification?: { id: string; availableActions: 'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'[]; direction: 'incoming' | 'outgoing'; methods: 'qr' | 'sas'[]; purpose: 'login' | 'device'; state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; error?: { code: string; reason: string; }; otherDevice?: { id: string; name?: string; }; otherUserID?: string; qr?: { data: string; }; sas?: { emojis: string; decimals?: string; }; }`\n\n### Example\n\n```typescript\nimport BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop();\n\nconst response = await client.app.verifications.sas.confirm('x');\n\nconsole.log(response);\n```", + perLanguage: { + typescript: { + method: 'client.app.verifications.sas.confirm', + example: + "import BeeperDesktop from '@beeper/desktop-api';\n\nconst client = new BeeperDesktop({\n accessToken: process.env['BEEPER_ACCESS_TOKEN'], // This is the default and can be omitted\n});\n\nconst response = await client.app.verifications.sas.confirm('x');\n\nconsole.log(response.session);", + }, + python: { + method: 'app.verifications.sas.confirm', + example: + 'import os\nfrom beeper_desktop_api import BeeperDesktop\n\nclient = BeeperDesktop(\n access_token=os.environ.get("BEEPER_ACCESS_TOKEN"), # This is the default and can be omitted\n)\nresponse = client.app.verifications.sas.confirm(\n "x",\n)\nprint(response.session)', + }, + go: { + method: 'client.App.Verifications.SAS.Confirm', + example: + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/beeper/desktop-api-go"\n\t"github.com/beeper/desktop-api-go/option"\n)\n\nfunc main() {\n\tclient := beeperdesktopapi.NewClient(\n\t\toption.WithAccessToken("My Access Token"),\n\t)\n\tresponse, err := client.App.Verifications.SAS.Confirm(context.TODO(), "x")\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", response.Session)\n}\n', + }, + cli: { + method: 'sas confirm', + example: + "beeper-desktop app:verifications:sas confirm \\\n --access-token 'My Access Token' \\\n --verification-id x", + }, + php: { + method: 'app->verifications->sas->confirm', + example: + "app->verifications->sas->confirm('x');\n\nvar_dump($response);", + }, + http: { + example: + 'curl http://localhost:23373/v1/app/setup/verifications/$VERIFICATION_ID/sas/confirm \\\n -X POST \\\n -H "Authorization: Bearer $BEEPER_ACCESS_TOKEN"', + }, + }, + }, ]; const EMBEDDED_READMES: { language: string; content: string }[] = [ diff --git a/packages/mcp-server/src/methods.ts b/packages/mcp-server/src/methods.ts index cf21e810..6dfb3ad5 100644 --- a/packages/mcp-server/src/methods.ts +++ b/packages/mcp-server/src/methods.ts @@ -244,6 +244,108 @@ export const sdkMethods: SdkMethod[] = [ httpMethod: 'get', httpPath: '/v1/info', }, + { + clientCallName: 'client.app.session', + fullyQualifiedName: 'app.session', + httpMethod: 'get', + httpPath: '/v1/app/setup', + }, + { + clientCallName: 'client.app.login.email', + fullyQualifiedName: 'app.login.email', + httpMethod: 'post', + httpPath: '/v1/app/setup/email', + }, + { + clientCallName: 'client.app.login.register', + fullyQualifiedName: 'app.login.register', + httpMethod: 'post', + httpPath: '/v1/app/setup/register', + }, + { + clientCallName: 'client.app.login.response', + fullyQualifiedName: 'app.login.response', + httpMethod: 'post', + httpPath: '/v1/app/setup/response', + }, + { + clientCallName: 'client.app.login.start', + fullyQualifiedName: 'app.login.start', + httpMethod: 'post', + httpPath: '/v1/app/setup/start', + }, + { + clientCallName: 'client.app.login.verification.recoveryKey.verify', + fullyQualifiedName: 'app.login.verification.recoveryKey.verify', + httpMethod: 'post', + httpPath: '/v1/app/setup/verification/recovery-key', + }, + { + clientCallName: 'client.app.login.verification.recoveryKey.reset.create', + fullyQualifiedName: 'app.login.verification.recoveryKey.reset.create', + httpMethod: 'post', + httpPath: '/v1/app/setup/verification/recovery-key/reset', + }, + { + clientCallName: 'client.app.login.verification.recoveryKey.reset.confirm', + fullyQualifiedName: 'app.login.verification.recoveryKey.reset.confirm', + httpMethod: 'post', + httpPath: '/v1/app/setup/verification/recovery-key/reset/confirm', + }, + { + clientCallName: 'client.app.verifications.create', + fullyQualifiedName: 'app.verifications.create', + httpMethod: 'post', + httpPath: '/v1/app/setup/verifications', + }, + { + clientCallName: 'client.app.verifications.retrieve', + fullyQualifiedName: 'app.verifications.retrieve', + httpMethod: 'get', + httpPath: '/v1/app/setup/verifications/{verificationID}', + }, + { + clientCallName: 'client.app.verifications.list', + fullyQualifiedName: 'app.verifications.list', + httpMethod: 'get', + httpPath: '/v1/app/setup/verifications', + }, + { + clientCallName: 'client.app.verifications.accept', + fullyQualifiedName: 'app.verifications.accept', + httpMethod: 'post', + httpPath: '/v1/app/setup/verifications/{verificationID}/accept', + }, + { + clientCallName: 'client.app.verifications.cancel', + fullyQualifiedName: 'app.verifications.cancel', + httpMethod: 'post', + httpPath: '/v1/app/setup/verifications/{verificationID}/cancel', + }, + { + clientCallName: 'client.app.verifications.qr.confirmScanned', + fullyQualifiedName: 'app.verifications.qr.confirmScanned', + httpMethod: 'post', + httpPath: '/v1/app/setup/verifications/{verificationID}/qr/confirm-scanned', + }, + { + clientCallName: 'client.app.verifications.qr.scan', + fullyQualifiedName: 'app.verifications.qr.scan', + httpMethod: 'post', + httpPath: '/v1/app/setup/verifications/qr/scan', + }, + { + clientCallName: 'client.app.verifications.sas.confirm', + fullyQualifiedName: 'app.verifications.sas.confirm', + httpMethod: 'post', + httpPath: '/v1/app/setup/verifications/{verificationID}/sas/confirm', + }, + { + clientCallName: 'client.app.verifications.sas.start', + fullyQualifiedName: 'app.verifications.sas.start', + httpMethod: 'post', + httpPath: '/v1/app/setup/verifications/{verificationID}/sas/start', + }, ]; function allowedMethodsForCodeTool(options: McpOptions | undefined): SdkMethod[] | undefined { diff --git a/src/client.ts b/src/client.ts index 49d3b8a3..edbc1e3a 100644 --- a/src/client.ts +++ b/src/client.ts @@ -56,7 +56,7 @@ import { AccountRetrieveResponse, Accounts, } from './resources/accounts/accounts'; -import { App, Verification } from './resources/app/app'; +import { App, AppSessionResponse, Verification } from './resources/app/app'; import { Bridge, BridgeListResponse, @@ -993,7 +993,7 @@ export declare namespace BeeperDesktop { export { Info as Info, type InfoRetrieveResponse as InfoRetrieveResponse }; - export { App as App, type Verification as Verification }; + export { App as App, type Verification as Verification, type AppSessionResponse as AppSessionResponse }; export type APIError = API.APIError; export type AppStateSnapshot = API.AppStateSnapshot; diff --git a/src/resources/app/app.ts b/src/resources/app/app.ts index 7edea82a..e55e7c09 100644 --- a/src/resources/app/app.ts +++ b/src/resources/app/app.ts @@ -2,15 +2,45 @@ import { APIResource } from '../../core/resource'; import * as LoginAPI from './login/login'; -import { BaseLogin, Login } from './login/login'; +import { + BaseLogin, + Login, + LoginEmailParams, + LoginRegisterParams, + LoginRegisterResponse, + LoginResponseParams, + LoginResponseResponse, + LoginStartResponse, +} from './login/login'; import * as VerificationsAPI from './verifications/verifications'; -import { BaseVerifications, Verifications } from './verifications/verifications'; +import { + BaseVerifications, + VerificationAcceptResponse, + VerificationCancelParams, + VerificationCancelResponse, + VerificationCreateParams, + VerificationCreateResponse, + VerificationListResponse, + VerificationRetrieveResponse, + Verifications, +} from './verifications/verifications'; +import { APIPromise } from '../../core/api-promise'; +import { RequestOptions } from '../../internal/request-options'; /** * Manage Beeper app login and encrypted messaging setup */ export class BaseApp extends APIResource { static override readonly _key: readonly ['app'] = Object.freeze(['app'] as const); + + /** + * Return the current Beeper Desktop or Beeper Server sign-in and encrypted + * messaging setup state. This endpoint is public before sign-in so apps can + * discover that sign-in is needed; after sign-in, pass a read token. + */ + session(options?: RequestOptions): APIPromise { + return this._client.get('/v1/app/setup', options); + } } /** * Manage Beeper app login and encrypted messaging setup @@ -137,15 +167,285 @@ export namespace Verification { } } +export interface AppSessionResponse { + /** + * Encrypted messaging setup status. + */ + e2ee: AppSessionResponse.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: AppSessionResponse.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: AppSessionResponse.Verification; +} + +export namespace AppSessionResponse { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + App.Login = Login; App.BaseLogin = BaseLogin; App.Verifications = Verifications; App.BaseVerifications = BaseVerifications; export declare namespace App { - export { type Verification as Verification }; + export { type Verification as Verification, type AppSessionResponse as AppSessionResponse }; - export { Login as Login, BaseLogin as BaseLogin }; + export { + Login as Login, + BaseLogin as BaseLogin, + type LoginRegisterResponse as LoginRegisterResponse, + type LoginResponseResponse as LoginResponseResponse, + type LoginStartResponse as LoginStartResponse, + type LoginEmailParams as LoginEmailParams, + type LoginRegisterParams as LoginRegisterParams, + type LoginResponseParams as LoginResponseParams, + }; - export { Verifications as Verifications, BaseVerifications as BaseVerifications }; + export { + Verifications as Verifications, + BaseVerifications as BaseVerifications, + type VerificationCreateResponse as VerificationCreateResponse, + type VerificationRetrieveResponse as VerificationRetrieveResponse, + type VerificationListResponse as VerificationListResponse, + type VerificationAcceptResponse as VerificationAcceptResponse, + type VerificationCancelResponse as VerificationCancelResponse, + type VerificationCreateParams as VerificationCreateParams, + type VerificationCancelParams as VerificationCancelParams, + }; } diff --git a/src/resources/app/index.ts b/src/resources/app/index.ts index 1a24e59f..d1fd3012 100644 --- a/src/resources/app/index.ts +++ b/src/resources/app/index.ts @@ -1,5 +1,24 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { App, BaseApp, type Verification } from './app'; -export { Login, BaseLogin } from './login/index'; -export { Verifications, BaseVerifications } from './verifications/index'; +export { App, BaseApp, type Verification, type AppSessionResponse } from './app'; +export { + Login, + BaseLogin, + type LoginRegisterResponse, + type LoginResponseResponse, + type LoginStartResponse, + type LoginEmailParams, + type LoginRegisterParams, + type LoginResponseParams, +} from './login/index'; +export { + Verifications, + BaseVerifications, + type VerificationCreateResponse, + type VerificationRetrieveResponse, + type VerificationListResponse, + type VerificationAcceptResponse, + type VerificationCancelResponse, + type VerificationCreateParams, + type VerificationCancelParams, +} from './verifications/index'; diff --git a/src/resources/app/login/index.ts b/src/resources/app/login/index.ts index b856af75..b1a5c5bf 100644 --- a/src/resources/app/login/index.ts +++ b/src/resources/app/login/index.ts @@ -1,4 +1,13 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Login, BaseLogin } from './login'; +export { + Login, + BaseLogin, + type LoginRegisterResponse, + type LoginResponseResponse, + type LoginStartResponse, + type LoginEmailParams, + type LoginRegisterParams, + type LoginResponseParams, +} from './login'; export { Verification, BaseVerification } from './verification/index'; diff --git a/src/resources/app/login/login.ts b/src/resources/app/login/login.ts index 920583d0..359f2be7 100644 --- a/src/resources/app/login/login.ts +++ b/src/resources/app/login/login.ts @@ -2,13 +2,53 @@ import { APIResource } from '../../../core/resource'; import * as VerificationAPI from './verification/verification'; -import { BaseVerification, Verification } from './verification/verification'; +import { BaseVerification, Verification as VerificationAPIVerification } from './verification/verification'; +import { APIPromise } from '../../../core/api-promise'; +import { buildHeaders } from '../../../internal/headers'; +import { RequestOptions } from '../../../internal/request-options'; /** * Complete first-party Beeper app login */ export class BaseLogin extends APIResource { static override readonly _key: readonly ['app', 'login'] = Object.freeze(['app', 'login'] as const); + + /** + * Send a sign-in code to the user email address for app setup. + */ + email(body: LoginEmailParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/setup/email', { + body, + ...options, + headers: buildHeaders([{ Accept: '*/*' }, options?.headers]), + __security: {}, + }); + } + + /** + * Create a Beeper account after the user chooses a username and accepts the Terms + * of Use. + */ + register(body: LoginRegisterParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/setup/register', { body, ...options, __security: {} }); + } + + /** + * Finish setup sign-in with the code sent to the user email address. If the user + * needs a new account, the response includes account creation copy and username + * suggestions. + */ + response(body: LoginResponseParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/setup/response', { body, ...options, __security: {} }); + } + + /** + * Start setting up Beeper Desktop or Beeper Server. The flow supports existing + * Beeper accounts and new account creation. + */ + start(options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/setup/start', { ...options, __security: {} }); + } } /** * Complete first-party Beeper app login @@ -17,9 +57,724 @@ export class Login extends BaseLogin { verification: VerificationAPI.Verification = new VerificationAPI.Verification(this._client); } -Login.Verification = Verification; +export interface LoginRegisterResponse { + /** + * Account credentials for first-party app setup. + */ + matrix: LoginRegisterResponse.Matrix; + + /** + * Current app sign-in and encrypted messaging setup state after sign-in. + */ + session: LoginRegisterResponse.Session; +} + +export namespace LoginRegisterResponse { + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Beeper account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Current app sign-in and encrypted messaging setup state after sign-in. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } +} + +export type LoginResponseResponse = + | LoginResponseResponse.Success + | LoginResponseResponse.RegistrationRequired; + +export namespace LoginResponseResponse { + export interface Success { + /** + * Account credentials for first-party app setup. + */ + matrix: Success.Matrix; + + /** + * Current app sign-in and encrypted messaging setup state after sign-in. + */ + session: Success.Session; + } + + export namespace Success { + /** + * Account credentials for first-party app setup. + */ + export interface Matrix { + /** + * Beeper account access token. Returned once for first-party app setup. + */ + accessToken: string; + + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Current app sign-in and encrypted messaging setup state after sign-in. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + } + + export interface RegistrationRequired { + /** + * Copy to display during account creation. + */ + copy: RegistrationRequired.Copy; + + /** + * Registration token returned by Beeper. + */ + leadToken: string; + + /** + * Indicates that the user needs to create a Beeper account. + */ + registrationRequired: true; + + /** + * Setup request ID to use when creating the account. + */ + setupRequestID: string; + + /** + * Suggested usernames for the new account. + */ + usernameSuggestions?: Array; + } + + export namespace RegistrationRequired { + /** + * Copy to display during account creation. + */ + export interface Copy { + /** + * Submit button label. + */ + submit: 'Continue'; + + /** + * Terms and privacy notice to show before account creation. + */ + terms: 'By continuing, you agree to the Terms of Use and acknowledge the Privacy Policy.'; + + /** + * Title for the username step. + */ + title: 'Choose your username'; + + /** + * Placeholder for the username field. + */ + usernamePlaceholder: 'Username'; + } + } +} + +export interface LoginStartResponse { + /** + * Setup request ID to use in the next sign-in step. + */ + setupRequestID: string; + + /** + * Available sign-in methods for this setup request. + */ + signInMethods: Array; +} + +export interface LoginEmailParams { + /** + * Email address to send the sign-in code to. + */ + email: string; + + /** + * Setup request ID returned by the start step. + */ + setupRequestID: string; +} + +export interface LoginRegisterParams { + /** + * Confirms that the user agreed to our + * [terms of use](https://www.beeper.com/terms-onboarding) and has read our + * [privacy policy](https://www.beeper.com/privacy). + */ + acceptTerms: true; + + /** + * Registration token returned by Beeper. + */ + leadToken: string; + + /** + * Setup request ID returned by the start step. + */ + setupRequestID: string; + + /** + * Username selected by the user. + */ + username: string; +} + +export interface LoginResponseParams { + /** + * Sign-in code from the user email. + */ + response: string; + + /** + * Setup request ID returned by the start step. + */ + setupRequestID: string; +} + +Login.Verification = VerificationAPIVerification; Login.BaseVerification = BaseVerification; export declare namespace Login { - export { Verification as Verification, BaseVerification as BaseVerification }; + export { + type LoginRegisterResponse as LoginRegisterResponse, + type LoginResponseResponse as LoginResponseResponse, + type LoginStartResponse as LoginStartResponse, + type LoginEmailParams as LoginEmailParams, + type LoginRegisterParams as LoginRegisterParams, + type LoginResponseParams as LoginResponseParams, + }; + + export { VerificationAPIVerification as Verification, BaseVerification as BaseVerification }; } diff --git a/src/resources/app/login/verification/index.ts b/src/resources/app/login/verification/index.ts index cde79e35..a24d5e5e 100644 --- a/src/resources/app/login/verification/index.ts +++ b/src/resources/app/login/verification/index.ts @@ -1,4 +1,9 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { RecoveryKey, BaseRecoveryKey } from './recovery-key/index'; +export { + RecoveryKey, + BaseRecoveryKey, + type RecoveryKeyVerifyResponse, + type RecoveryKeyVerifyParams, +} from './recovery-key/index'; export { Verification, BaseVerification } from './verification'; diff --git a/src/resources/app/login/verification/recovery-key/index.ts b/src/resources/app/login/verification/recovery-key/index.ts index 3e2be45d..e0dbac2d 100644 --- a/src/resources/app/login/verification/recovery-key/index.ts +++ b/src/resources/app/login/verification/recovery-key/index.ts @@ -1,4 +1,16 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { RecoveryKey, BaseRecoveryKey } from './recovery-key'; -export { Reset, BaseReset } from './reset'; +export { + RecoveryKey, + BaseRecoveryKey, + type RecoveryKeyVerifyResponse, + type RecoveryKeyVerifyParams, +} from './recovery-key'; +export { + Reset, + BaseReset, + type ResetCreateResponse, + type ResetConfirmResponse, + type ResetCreateParams, + type ResetConfirmParams, +} from './reset'; diff --git a/src/resources/app/login/verification/recovery-key/recovery-key.ts b/src/resources/app/login/verification/recovery-key/recovery-key.ts index 1de1a7e1..306da97b 100644 --- a/src/resources/app/login/verification/recovery-key/recovery-key.ts +++ b/src/resources/app/login/verification/recovery-key/recovery-key.ts @@ -2,8 +2,20 @@ import { APIResource } from '../../../../../core/resource'; import * as ResetAPI from './reset'; -import { BaseReset, Reset } from './reset'; +import { + BaseReset, + Reset, + ResetConfirmParams, + ResetConfirmResponse, + ResetCreateParams, + ResetCreateResponse, +} from './reset'; +import { APIPromise } from '../../../../../core/api-promise'; +import { RequestOptions } from '../../../../../internal/request-options'; +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop and Beeper Server. + */ export class BaseRecoveryKey extends APIResource { static override readonly _key: readonly ['app', 'login', 'verification', 'recoveryKey'] = Object.freeze([ 'app', @@ -11,14 +23,306 @@ export class BaseRecoveryKey extends APIResource { 'verification', 'recoveryKey', ] as const); + + /** + * Unlock encrypted messages with the user recovery key. + */ + verify(body: RecoveryKeyVerifyParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/setup/verification/recovery-key', { body, ...options }); + } } +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop and Beeper Server. + */ export class RecoveryKey extends BaseRecoveryKey { reset: ResetAPI.Reset = new ResetAPI.Reset(this._client); } +export interface RecoveryKeyVerifyResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: RecoveryKeyVerifyResponse.Session; +} + +export namespace RecoveryKeyVerifyResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } +} + +export interface RecoveryKeyVerifyParams { + /** + * Recovery key saved by the user. + */ + recoveryKey: string; +} + RecoveryKey.Reset = Reset; RecoveryKey.BaseReset = BaseReset; export declare namespace RecoveryKey { - export { Reset as Reset, BaseReset as BaseReset }; + export { + type RecoveryKeyVerifyResponse as RecoveryKeyVerifyResponse, + type RecoveryKeyVerifyParams as RecoveryKeyVerifyParams, + }; + + export { + Reset as Reset, + BaseReset as BaseReset, + type ResetCreateResponse as ResetCreateResponse, + type ResetConfirmResponse as ResetConfirmResponse, + type ResetCreateParams as ResetCreateParams, + type ResetConfirmParams as ResetConfirmParams, + }; } diff --git a/src/resources/app/login/verification/recovery-key/reset.ts b/src/resources/app/login/verification/recovery-key/reset.ts index 278908d4..7f801b38 100644 --- a/src/resources/app/login/verification/recovery-key/reset.ts +++ b/src/resources/app/login/verification/recovery-key/reset.ts @@ -1,9 +1,590 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../../../../core/resource'; +import { APIPromise } from '../../../../../core/api-promise'; +import { RequestOptions } from '../../../../../internal/request-options'; +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop and Beeper Server. + */ export class BaseReset extends APIResource { static override readonly _key: readonly ['app', 'login', 'verification', 'recoveryKey', 'reset'] = Object.freeze(['app', 'login', 'verification', 'recoveryKey', 'reset'] as const); + + /** + * Create a new recovery key when the user cannot use the existing one. + */ + create( + body: ResetCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/v1/app/setup/verification/recovery-key/reset', { body, ...options }); + } + + /** + * Confirm that the new recovery key should be used for this account. + */ + confirm(body: ResetConfirmParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/setup/verification/recovery-key/reset/confirm', { body, ...options }); + } } +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop and Beeper Server. + */ export class Reset extends BaseReset {} + +export interface ResetCreateResponse { + /** + * New recovery key. Show it once and ask the user to save it. + */ + recoveryKey: string; + + /** + * Current app sign-in and encrypted messaging setup state after creating the new + * recovery key. + */ + session: ResetCreateResponse.Session; +} + +export namespace ResetCreateResponse { + /** + * Current app sign-in and encrypted messaging setup state after creating the new + * recovery key. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } +} + +export interface ResetConfirmResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: ResetConfirmResponse.Session; +} + +export namespace ResetConfirmResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } +} + +export interface ResetCreateParams { + /** + * Existing recovery key, if the user has it. + */ + existingRecoveryKey?: string; +} + +export interface ResetConfirmParams { + /** + * New recovery key returned by the reset step. + */ + recoveryKey: string; +} + +export declare namespace Reset { + export { + type ResetCreateResponse as ResetCreateResponse, + type ResetConfirmResponse as ResetConfirmResponse, + type ResetCreateParams as ResetCreateParams, + type ResetConfirmParams as ResetConfirmParams, + }; +} diff --git a/src/resources/app/login/verification/verification.ts b/src/resources/app/login/verification/verification.ts index a1c86be7..0583568a 100644 --- a/src/resources/app/login/verification/verification.ts +++ b/src/resources/app/login/verification/verification.ts @@ -2,7 +2,12 @@ import { APIResource } from '../../../../core/resource'; import * as RecoveryKeyAPI from './recovery-key/recovery-key'; -import { BaseRecoveryKey, RecoveryKey } from './recovery-key/recovery-key'; +import { + BaseRecoveryKey, + RecoveryKey, + RecoveryKeyVerifyParams, + RecoveryKeyVerifyResponse, +} from './recovery-key/recovery-key'; export class BaseVerification extends APIResource { static override readonly _key: readonly ['app', 'login', 'verification'] = Object.freeze([ @@ -19,5 +24,10 @@ Verification.RecoveryKey = RecoveryKey; Verification.BaseRecoveryKey = BaseRecoveryKey; export declare namespace Verification { - export { RecoveryKey as RecoveryKey, BaseRecoveryKey as BaseRecoveryKey }; + export { + RecoveryKey as RecoveryKey, + BaseRecoveryKey as BaseRecoveryKey, + type RecoveryKeyVerifyResponse as RecoveryKeyVerifyResponse, + type RecoveryKeyVerifyParams as RecoveryKeyVerifyParams, + }; } diff --git a/src/resources/app/verifications/index.ts b/src/resources/app/verifications/index.ts index 995a801b..a8a8aacb 100644 --- a/src/resources/app/verifications/index.ts +++ b/src/resources/app/verifications/index.ts @@ -1,5 +1,15 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export { Qr, BaseQr } from './qr'; -export { SAS, BaseSAS } from './sas'; -export { Verifications, BaseVerifications } from './verifications'; +export { Qr, BaseQr, type QrConfirmScannedResponse, type QrScanResponse, type QrScanParams } from './qr'; +export { SAS, BaseSAS, type SASConfirmResponse, type SASStartResponse } from './sas'; +export { + Verifications, + BaseVerifications, + type VerificationCreateResponse, + type VerificationRetrieveResponse, + type VerificationListResponse, + type VerificationAcceptResponse, + type VerificationCancelResponse, + type VerificationCreateParams, + type VerificationCancelParams, +} from './verifications'; diff --git a/src/resources/app/verifications/qr.ts b/src/resources/app/verifications/qr.ts index 50724e09..0950844d 100644 --- a/src/resources/app/verifications/qr.ts +++ b/src/resources/app/verifications/qr.ts @@ -1,12 +1,820 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop and Beeper Server. + */ export class BaseQr extends APIResource { static override readonly _key: readonly ['app', 'verifications', 'qr'] = Object.freeze([ 'app', 'verifications', 'qr', ] as const); + + /** + * Confirm that another device scanned this device QR code. + */ + confirmScanned(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/setup/verifications/${verificationID}/qr/confirm-scanned`, options); + } + + /** + * Submit the QR code scanned from another signed-in device. + */ + scan(body: QrScanParams, options?: RequestOptions): APIPromise { + return this._client.post('/v1/app/setup/verifications/qr/scan', { body, ...options }); + } } +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop and Beeper Server. + */ export class Qr extends BaseQr {} + +export interface QrConfirmScannedResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: QrConfirmScannedResponse.Session; + + /** + * Trusted device verification progress. + */ + verification?: QrConfirmScannedResponse.Verification; +} + +export namespace QrConfirmScannedResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface QrScanResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: QrScanResponse.Session; + + /** + * Trusted device verification progress. + */ + verification?: QrScanResponse.Verification; +} + +export namespace QrScanResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface QrScanParams { + /** + * QR code payload scanned from the other device. + */ + data: string; +} + +export declare namespace Qr { + export { + type QrConfirmScannedResponse as QrConfirmScannedResponse, + type QrScanResponse as QrScanResponse, + type QrScanParams as QrScanParams, + }; +} diff --git a/src/resources/app/verifications/sas.ts b/src/resources/app/verifications/sas.ts index d805f9f8..9adfdcf1 100644 --- a/src/resources/app/verifications/sas.ts +++ b/src/resources/app/verifications/sas.ts @@ -1,12 +1,809 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../../../core/resource'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop and Beeper Server. + */ export class BaseSAS extends APIResource { static override readonly _key: readonly ['app', 'verifications', 'sas'] = Object.freeze([ 'app', 'verifications', 'sas', ] as const); + + /** + * Confirm that the emoji or number sequence matches on both devices. + */ + confirm(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/setup/verifications/${verificationID}/sas/confirm`, options); + } + + /** + * Start emoji comparison for device verification. + */ + start(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/setup/verifications/${verificationID}/sas/start`, options); + } } +/** + * First-party sign-in and encrypted messaging setup for Beeper Desktop and Beeper Server. + */ export class SAS extends BaseSAS {} + +export interface SASConfirmResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: SASConfirmResponse.Session; + + /** + * Trusted device verification progress. + */ + verification?: SASConfirmResponse.Verification; +} + +export namespace SASConfirmResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface SASStartResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: SASStartResponse.Session; + + /** + * Trusted device verification progress. + */ + verification?: SASStartResponse.Verification; +} + +export namespace SASStartResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export declare namespace SAS { + export { type SASConfirmResponse as SASConfirmResponse, type SASStartResponse as SASStartResponse }; +} diff --git a/src/resources/app/verifications/verifications.ts b/src/resources/app/verifications/verifications.ts index ecd71b41..6749911e 100644 --- a/src/resources/app/verifications/verifications.ts +++ b/src/resources/app/verifications/verifications.ts @@ -2,9 +2,12 @@ import { APIResource } from '../../../core/resource'; import * as QrAPI from './qr'; -import { BaseQr, Qr } from './qr'; +import { BaseQr, Qr as QrAPIQr, QrConfirmScannedResponse, QrScanParams, QrScanResponse } from './qr'; import * as SASAPI from './sas'; -import { BaseSAS, SAS } from './sas'; +import { BaseSAS, SAS as SasapiSAS, SASConfirmResponse, SASStartResponse } from './sas'; +import { APIPromise } from '../../../core/api-promise'; +import { RequestOptions } from '../../../internal/request-options'; +import { path } from '../../../internal/utils/path'; /** * Manage device verification transactions @@ -14,6 +17,52 @@ export class BaseVerifications extends APIResource { 'app', 'verifications', ] as const); + + /** + * Start verifying this device from another signed-in device. + */ + create( + body: VerificationCreateParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post('/v1/app/setup/verifications', { body, ...options }); + } + + /** + * Get the current state of a device verification transaction. + */ + retrieve(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.get(path`/v1/app/setup/verifications/${verificationID}`, options); + } + + /** + * List pending and active device verifications. Use this to recover state without + * a WebSocket connection. + */ + list(options?: RequestOptions): APIPromise { + return this._client.get('/v1/app/setup/verifications', options); + } + + /** + * Accept an incoming device verification request. + */ + accept(verificationID: string, options?: RequestOptions): APIPromise { + return this._client.post(path`/v1/app/setup/verifications/${verificationID}/accept`, options); + } + + /** + * Cancel an active device verification request. + */ + cancel( + verificationID: string, + body: VerificationCancelParams | null | undefined = {}, + options?: RequestOptions, + ): APIPromise { + return this._client.post(path`/v1/app/setup/verifications/${verificationID}/cancel`, { + body, + ...options, + }); + } } /** * Manage device verification transactions @@ -23,13 +72,1721 @@ export class Verifications extends BaseVerifications { sas: SASAPI.SAS = new SASAPI.SAS(this._client); } -Verifications.Qr = Qr; +export interface VerificationCreateResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: VerificationCreateResponse.Session; + + /** + * Trusted device verification progress. + */ + verification?: VerificationCreateResponse.Verification; +} + +export namespace VerificationCreateResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationRetrieveResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: VerificationRetrieveResponse.Session; + + /** + * Trusted device verification progress. + */ + verification?: VerificationRetrieveResponse.Verification; +} + +export namespace VerificationRetrieveResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationListResponse { + items: Array; +} + +export namespace VerificationListResponse { + /** + * Trusted device verification progress. + */ + export interface Item { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Item.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Item.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Item.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Item.SAS; + } + + export namespace Item { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationAcceptResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: VerificationAcceptResponse.Session; + + /** + * Trusted device verification progress. + */ + verification?: VerificationAcceptResponse.Verification; +} + +export namespace VerificationAcceptResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationCancelResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + session: VerificationCancelResponse.Session; + + /** + * Trusted device verification progress. + */ + verification?: VerificationCancelResponse.Verification; +} + +export namespace VerificationCancelResponse { + /** + * Current app sign-in and encrypted messaging setup state. + */ + export interface Session { + /** + * Encrypted messaging setup status. + */ + e2ee: Session.E2EE; + + /** + * Current sign-in and encrypted messaging setup state for Beeper Desktop or Beeper + * Server. + */ + state: + | 'needs-login' + | 'initializing' + | 'needs-cross-signing-setup' + | 'needs-verification' + | 'needs-secrets' + | 'needs-first-sync' + | 'ready'; + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + matrix?: Session.Matrix; + + /** + * Trusted device verification progress. + */ + verification?: Session.Verification; + } + + export namespace Session { + /** + * Encrypted messaging setup status. + */ + export interface E2EE { + /** + * Whether this account can verify trusted devices. + */ + crossSigning: boolean; + + /** + * Whether the first encrypted message sync is complete. + */ + firstSyncDone: boolean; + + /** + * Whether the user confirmed that they saved their recovery key. + */ + hasBackedUpRecoveryKey: boolean; + + /** + * Whether encrypted messaging setup has started. + */ + initialized: boolean; + + /** + * Whether encrypted message backup is available. + */ + keyBackup: boolean; + + /** + * Encrypted messaging keys available on this device. + */ + secrets: E2EE.Secrets; + + /** + * Whether secure key storage is available. + */ + secretStorage: boolean; + + /** + * Whether this device is trusted for encrypted messages. + */ + verified: boolean; + + /** + * Unix timestamp for when the recovery key was created. + */ + recoveryKeyGeneratedAt?: number; + } + + export namespace E2EE { + /** + * Encrypted messaging keys available on this device. + */ + export interface Secrets { + /** + * Whether the account identity key is available. + */ + masterKey: boolean; + + /** + * Whether the encrypted message backup key is available. + */ + megolmBackupKey: boolean; + + /** + * Whether a recovery key is available. + */ + recoveryKey: boolean; + + /** + * Whether the device trust key is available. + */ + selfSigningKey: boolean; + + /** + * Whether the user trust key is available. + */ + userSigningKey: boolean; + } + } + + /** + * Signed-in account details. Omitted until sign-in is complete. + */ + export interface Matrix { + /** + * Current device ID. + */ + deviceID: string; + + /** + * Beeper homeserver URL for this account. + */ + homeserver: string; + + /** + * Signed-in Beeper user ID. + */ + userID: string; + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } + } + + /** + * Trusted device verification progress. + */ + export interface Verification { + /** + * Verification ID to pass in verification action paths. + */ + id: string; + + /** + * Verification actions that are valid for the current state. + */ + availableActions: Array<'accept' | 'cancel' | 'qr.confirmScanned' | 'sas.start' | 'sas.confirm'>; + + /** + * Whether this device started or received the verification. + */ + direction: 'incoming' | 'outgoing'; + + /** + * Verification methods supported for this transaction. + */ + methods: Array<'qr' | 'sas'>; + + /** + * Why this verification exists. + */ + purpose: 'login' | 'device'; + + /** + * Current trusted-device verification state. + */ + state: 'requested' | 'ready' | 'sas_ready' | 'qr_scanned' | 'done' | 'cancelled' | 'error'; + + /** + * Verification error details, if verification stopped. + */ + error?: Verification.Error; + + /** + * Other device participating in verification. + */ + otherDevice?: Verification.OtherDevice; + + /** + * Other Beeper user participating in verification. + */ + otherUserID?: string; + + /** + * QR verification data. + */ + qr?: Verification.Qr; + + /** + * Emoji or number comparison data for verification. + */ + sas?: Verification.SAS; + } + + export namespace Verification { + /** + * Verification error details, if verification stopped. + */ + export interface Error { + /** + * Verification error code. + */ + code: string; + + /** + * User-facing verification error message. + */ + reason: string; + } + + /** + * Other device participating in verification. + */ + export interface OtherDevice { + /** + * Other device ID. + */ + id: string; + + /** + * Other device display name, if known. + */ + name?: string; + } + + /** + * QR verification data. + */ + export interface Qr { + /** + * QR code payload to display for verification. + */ + data: string; + } + + /** + * Emoji or number comparison data for verification. + */ + export interface SAS { + /** + * Emoji sequence to compare on both devices. + */ + emojis: string; + + /** + * Number sequence to compare on both devices. + */ + decimals?: string; + } + } +} + +export interface VerificationCreateParams { + /** + * Why this verification is being started. + */ + purpose?: 'login' | 'device'; + + /** + * Beeper user ID to verify. Defaults to the signed-in user. + */ + userID?: string; +} + +export interface VerificationCancelParams { + /** + * Optional cancellation code. + */ + code?: string; + + /** + * Optional user-facing cancellation reason. + */ + reason?: string; +} + +Verifications.Qr = QrAPIQr; Verifications.BaseQr = BaseQr; -Verifications.SAS = SAS; +Verifications.SAS = SasapiSAS; Verifications.BaseSAS = BaseSAS; export declare namespace Verifications { - export { Qr as Qr, BaseQr as BaseQr }; + export { + type VerificationCreateResponse as VerificationCreateResponse, + type VerificationRetrieveResponse as VerificationRetrieveResponse, + type VerificationListResponse as VerificationListResponse, + type VerificationAcceptResponse as VerificationAcceptResponse, + type VerificationCancelResponse as VerificationCancelResponse, + type VerificationCreateParams as VerificationCreateParams, + type VerificationCancelParams as VerificationCancelParams, + }; + + export { + QrAPIQr as Qr, + BaseQr as BaseQr, + type QrConfirmScannedResponse as QrConfirmScannedResponse, + type QrScanResponse as QrScanResponse, + type QrScanParams as QrScanParams, + }; - export { SAS as SAS, BaseSAS as BaseSAS }; + export { + SasapiSAS as SAS, + BaseSAS as BaseSAS, + type SASConfirmResponse as SASConfirmResponse, + type SASStartResponse as SASStartResponse, + }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 60dd458a..0aadd8d0 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -9,7 +9,7 @@ export { type AccountRetrieveResponse, type AccountListResponse, } from './accounts/accounts'; -export { App, BaseApp, type Verification } from './app/app'; +export { App, BaseApp, type Verification, type AppSessionResponse } from './app/app'; export { Assets, BaseAssets, diff --git a/tests/api-resources/app/app.test.ts b/tests/api-resources/app/app.test.ts new file mode 100644 index 00000000..d433c3b1 --- /dev/null +++ b/tests/api-resources/app/app.test.ts @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseApp } from '@beeper/desktop-api/resources/app/app'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseApp], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: BaseApp }>) => { + test('session', async () => { + const responsePromise = client.app.session(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource app', () => runTests(client)); +describe('resource app (tree shakable, base)', () => runTests(partialClient)); diff --git a/tests/api-resources/app/login/login.test.ts b/tests/api-resources/app/login/login.test.ts new file mode 100644 index 00000000..5dfb7c7d --- /dev/null +++ b/tests/api-resources/app/login/login.test.ts @@ -0,0 +1,107 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { App } from '@beeper/desktop-api/resources/app/app'; +import { BaseLogin } from '@beeper/desktop-api/resources/app/login/login'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseLogin], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [App], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { login: BaseLogin } }>) => { + test('email: only required params', async () => { + const responsePromise = client.app.login.email({ + email: 'dev@stainless.com', + setupRequestID: 'setupRequestID', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('email: required and optional params', async () => { + const response = await client.app.login.email({ + email: 'dev@stainless.com', + setupRequestID: 'setupRequestID', + }); + }); + + test('register: only required params', async () => { + const responsePromise = client.app.login.register({ + acceptTerms: true, + leadToken: 'leadToken', + setupRequestID: 'setupRequestID', + username: 'x', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('register: required and optional params', async () => { + const response = await client.app.login.register({ + acceptTerms: true, + leadToken: 'leadToken', + setupRequestID: 'setupRequestID', + username: 'x', + }); + }); + + test('response: only required params', async () => { + const responsePromise = client.app.login.response({ + response: 'response', + setupRequestID: 'setupRequestID', + }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('response: required and optional params', async () => { + const response = await client.app.login.response({ + response: 'response', + setupRequestID: 'setupRequestID', + }); + }); + + test('start', async () => { + const responsePromise = client.app.login.start(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource login', () => runTests(client)); +describe('resource login (tree shakable, base)', () => runTests(partialClient)); +describe('resource login (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts b/tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts new file mode 100644 index 00000000..e54a0559 --- /dev/null +++ b/tests/api-resources/app/login/verification/recovery-key/recovery-key.test.ts @@ -0,0 +1,46 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { Verification } from '@beeper/desktop-api/resources/app/login/verification/verification'; +import { BaseRecoveryKey } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/recovery-key'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseRecoveryKey], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Verification], +}); + +const runTests = ( + client: PartialBeeperDesktop<{ app: { login: { verification: { recoveryKey: BaseRecoveryKey } } } }>, +) => { + test('verify: only required params', async () => { + const responsePromise = client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('verify: required and optional params', async () => { + const response = await client.app.login.verification.recoveryKey.verify({ recoveryKey: 'x' }); + }); +}; +describe('resource recoveryKey', () => runTests(client)); +describe('resource recoveryKey (tree shakable, base)', () => runTests(partialClient)); +describe('resource recoveryKey (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/login/verification/recovery-key/reset.test.ts b/tests/api-resources/app/login/verification/recovery-key/reset.test.ts new file mode 100644 index 00000000..178d978b --- /dev/null +++ b/tests/api-resources/app/login/verification/recovery-key/reset.test.ts @@ -0,0 +1,67 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { RecoveryKey } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/recovery-key'; +import { BaseReset } from '@beeper/desktop-api/resources/app/login/verification/recovery-key/reset'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseReset], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [RecoveryKey], +}); + +const runTests = ( + client: PartialBeeperDesktop<{ app: { login: { verification: { recoveryKey: { reset: BaseReset } } } } }>, +) => { + test('create', async () => { + const responsePromise = client.app.login.verification.recoveryKey.reset.create(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.app.login.verification.recoveryKey.reset.create( + { existingRecoveryKey: 'existingRecoveryKey' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); + + test('confirm: only required params', async () => { + const responsePromise = client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('confirm: required and optional params', async () => { + const response = await client.app.login.verification.recoveryKey.reset.confirm({ recoveryKey: 'x' }); + }); +}; +describe('resource reset', () => runTests(client)); +describe('resource reset (tree shakable, base)', () => runTests(partialClient)); +describe('resource reset (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/verifications/qr.test.ts b/tests/api-resources/app/verifications/qr.test.ts new file mode 100644 index 00000000..fc09226d --- /dev/null +++ b/tests/api-resources/app/verifications/qr.test.ts @@ -0,0 +1,55 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseQr } from '@beeper/desktop-api/resources/app/verifications/qr'; +import { Verifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseQr], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Verifications], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { verifications: { qr: BaseQr } } }>) => { + test('confirmScanned', async () => { + const responsePromise = client.app.verifications.qr.confirmScanned('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('scan: only required params', async () => { + const responsePromise = client.app.verifications.qr.scan({ data: 'x' }); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('scan: required and optional params', async () => { + const response = await client.app.verifications.qr.scan({ data: 'x' }); + }); +}; +describe('resource qr', () => runTests(client)); +describe('resource qr (tree shakable, base)', () => runTests(partialClient)); +describe('resource qr (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/verifications/sas.test.ts b/tests/api-resources/app/verifications/sas.test.ts new file mode 100644 index 00000000..5564a785 --- /dev/null +++ b/tests/api-resources/app/verifications/sas.test.ts @@ -0,0 +1,51 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { BaseSAS } from '@beeper/desktop-api/resources/app/verifications/sas'; +import { Verifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseSAS], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [Verifications], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { verifications: { sas: BaseSAS } } }>) => { + test('confirm', async () => { + const responsePromise = client.app.verifications.sas.confirm('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('start', async () => { + const responsePromise = client.app.verifications.sas.start('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); +}; +describe('resource sas', () => runTests(client)); +describe('resource sas (tree shakable, base)', () => runTests(partialClient)); +describe('resource sas (tree shakable, subresource)', () => runTests(parentPartialClient)); diff --git a/tests/api-resources/app/verifications/verifications.test.ts b/tests/api-resources/app/verifications/verifications.test.ts new file mode 100644 index 00000000..076b9daf --- /dev/null +++ b/tests/api-resources/app/verifications/verifications.test.ts @@ -0,0 +1,105 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import { App } from '@beeper/desktop-api/resources/app/app'; +import { BaseVerifications } from '@beeper/desktop-api/resources/app/verifications/verifications'; + +import BeeperDesktop from '@beeper/desktop-api'; +import { createClient, type PartialBeeperDesktop } from '@beeper/desktop-api/tree-shakable'; + +const client = new BeeperDesktop({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', +}); + +const partialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [BaseVerifications], +}); + +const parentPartialClient = createClient({ + accessToken: 'My Access Token', + baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', + resources: [App], +}); + +const runTests = (client: PartialBeeperDesktop<{ app: { verifications: BaseVerifications } }>) => { + test('create', async () => { + const responsePromise = client.app.verifications.create(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('create: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.app.verifications.create( + { purpose: 'login', userID: 'userID' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); + + test('retrieve', async () => { + const responsePromise = client.app.verifications.retrieve('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('list', async () => { + const responsePromise = client.app.verifications.list(); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('accept', async () => { + const responsePromise = client.app.verifications.accept('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('cancel', async () => { + const responsePromise = client.app.verifications.cancel('x'); + const rawResponse = await responsePromise.asResponse(); + expect(rawResponse).toBeInstanceOf(Response); + const response = await responsePromise; + expect(response).not.toBeInstanceOf(Response); + const dataAndResponse = await responsePromise.withResponse(); + expect(dataAndResponse.data).toBe(response); + expect(dataAndResponse.response).toBe(rawResponse); + }); + + test('cancel: request options and params are passed correctly', async () => { + // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error + await expect( + client.app.verifications.cancel( + 'x', + { code: 'code', reason: 'reason' }, + { path: '/_stainless_unknown_path' }, + ), + ).rejects.toThrow(BeeperDesktop.NotFoundError); + }); +}; +describe('resource verifications', () => runTests(client)); +describe('resource verifications (tree shakable, base)', () => runTests(partialClient)); +describe('resource verifications (tree shakable, subresource)', () => runTests(parentPartialClient)); From 91bb8861dbbe6cbf63c3c8f6a3a03c76d579c084 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 02:36:05 +0000 Subject: [PATCH 13/17] chore(tests): remove redundant File import --- tests/uploads.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/uploads.test.ts b/tests/uploads.test.ts index e13ed285..3cbef94c 100644 --- a/tests/uploads.test.ts +++ b/tests/uploads.test.ts @@ -1,7 +1,6 @@ import fs from 'fs'; import type { ResponseLike } from '@beeper/desktop-api/internal/to-file'; import { toFile } from '@beeper/desktop-api/core/uploads'; -import { File } from 'node:buffer'; class MyClass { name: string = 'foo'; From 550009b71f922f605d4ca0e0059bbed6627e5fbe Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 19 May 2026 02:36:41 +0000 Subject: [PATCH 14/17] fix(typescript): upgrade tsc-multi so that it works with Node 26 --- package.json | 2 +- packages/mcp-server/package.json | 2 +- packages/mcp-server/yarn.lock | 6 +++--- yarn.lock | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 0943a761..0d17b1ad 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "publint": "^0.2.12", "ts-jest": "^29.1.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz", "tsconfig-paths": "^4.0.0", "tslib": "^2.8.1", "typescript": "5.8.3", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 67c9e044..6575b5e9 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -74,7 +74,7 @@ "ts-jest": "^29.1.0", "ts-morph": "^19.0.0", "ts-node": "^10.5.0", - "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz", + "tsc-multi": "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz", "tsconfig-paths": "^4.0.0" }, "imports": { diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index c7e37692..c6b17b02 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -3921,9 +3921,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.1" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": - version "1.1.9" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz": + version "1.1.11" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz#010247051be13b55abdc98f787c017285149f4f2" dependencies: debug "^4.3.7" fast-glob "^3.3.2" diff --git a/yarn.lock b/yarn.lock index 18e7cbdc..00842e32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3192,9 +3192,9 @@ ts-node@^10.5.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz": - version "1.1.9" - resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.9/tsc-multi.tgz#777f6f5d9e26bf0e94e5170990dd3a841d6707cd" +"tsc-multi@https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz": + version "1.1.11" + resolved "https://github.com/stainless-api/tsc-multi/releases/download/v1.1.11/tsc-multi.tgz#010247051be13b55abdc98f787c017285149f4f2" dependencies: debug "^4.3.7" fast-glob "^3.3.2" From 1db6c606b61fe36e7ee14a1e178b6cb31b67545a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 28 May 2026 02:11:21 +0000 Subject: [PATCH 15/17] chore(internal): codegen related update --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 00842e32..06fc1085 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1215,9 +1215,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.1.0" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.0.tgz#4f41a41190216ee36067ec381526fe9539c4f0ae" - integrity sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w== + version "2.1.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.1.tgz#c68b1c4111c76aae3a6fba55d496cee10c39dad8" + integrity sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA== dependencies: balanced-match "^1.0.0" From 1d9458098e244c852f32813b59ae558f8c61b11c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 02:26:07 +0000 Subject: [PATCH 16/17] fix(mcp): use `pure-lockfile` when building mcp server --- scripts/build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build b/scripts/build index cb002f77..98f637c1 100755 --- a/scripts/build +++ b/scripts/build @@ -52,6 +52,6 @@ fi # build all sub-packages for dir in packages/*; do if [ -d "$dir" ]; then - (cd "$dir" && yarn install && yarn build) + (cd "$dir" && yarn install --pure-lockfile && yarn build) fi done From 3c283ac6bea7a4ac0115105228ccd703f605a55d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 29 May 2026 02:26:35 +0000 Subject: [PATCH 17/17] release: 5.1.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 25 +++++++++++++++++++++++++ package.json | 2 +- packages/mcp-server/manifest.json | 2 +- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/server.ts | 2 +- src/version.ts | 2 +- 7 files changed, 31 insertions(+), 6 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 32dbe0e2..affd1ab3 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "5.0.0" + ".": "5.1.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 4932b1a8..4d135d37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## 5.1.0 (2026-05-29) + +Full Changelog: [v5.0.0...v5.1.0](https://github.com/beeper/desktop-api-js/compare/v5.0.0...v5.1.0) + +### Features + +* **api:** add login flow, verifications, recovery key methods to app ([b9c1714](https://github.com/beeper/desktop-api-js/commit/b9c1714410139c2139b597338cd002d785653e85)) +* **api:** api update ([0a91186](https://github.com/beeper/desktop-api-js/commit/0a91186fa1a0811dc9eeb9d43c8093aaeb115e95)) +* **api:** remove cli ([40669cb](https://github.com/beeper/desktop-api-js/commit/40669cb5d53274627d81fc4554d4c5d29647e373)) + + +### Bug Fixes + +* **mcp:** require auth for standalone HTTP server ([eb86fa5](https://github.com/beeper/desktop-api-js/commit/eb86fa551df33109e963e2faf304b0380ac504f2)) +* **mcp:** use `pure-lockfile` when building mcp server ([1d94580](https://github.com/beeper/desktop-api-js/commit/1d9458098e244c852f32813b59ae558f8c61b11c)) +* **typescript:** upgrade tsc-multi so that it works with Node 26 ([550009b](https://github.com/beeper/desktop-api-js/commit/550009b71f922f605d4ca0e0059bbed6627e5fbe)) + + +### Chores + +* **internal:** codegen related update ([1db6c60](https://github.com/beeper/desktop-api-js/commit/1db6c606b61fe36e7ee14a1e178b6cb31b67545a)) +* **internal:** regenerate SDK with no functional changes ([8b59f3a](https://github.com/beeper/desktop-api-js/commit/8b59f3a10dc81df3e61d1d467f221edf4fc2d032)) +* redact api-key headers in debug logs ([f34de70](https://github.com/beeper/desktop-api-js/commit/f34de708e01ce81a9cb6a9dcd180c44e76b4f2fd)) +* **tests:** remove redundant File import ([91bb886](https://github.com/beeper/desktop-api-js/commit/91bb8861dbbe6cbf63c3c8f6a3a03c76d579c084)) + ## 5.0.0 (2026-05-07) Full Changelog: [v4.8.0...v5.0.0](https://github.com/beeper/desktop-api-js/compare/v4.8.0...v5.0.0) diff --git a/package.json b/package.json index 0d17b1ad..e510903d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@beeper/desktop-api", - "version": "5.0.0", + "version": "5.1.0", "description": "The official TypeScript library for the Beeper Desktop API", "author": "Beeper Desktop ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index 07858738..4c124d10 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -1,7 +1,7 @@ { "dxt_version": "0.2", "name": "@beeper/desktop-mcp", - "version": "5.0.0", + "version": "5.1.0", "description": "The official MCP Server for the Beeper Desktop API", "author": { "name": "Beeper Desktop", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 6575b5e9..014babbd 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "@beeper/desktop-mcp", - "version": "5.0.0", + "version": "5.1.0", "description": "The official MCP Server for the Beeper Desktop API", "author": "Beeper Desktop ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 293ee947..3fdacca2 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -28,7 +28,7 @@ export const newMcpServer = async ({ new McpServer( { name: 'beeper_desktop_api_api', - version: '5.0.0', + version: '5.1.0', }, { instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }), diff --git a/src/version.ts b/src/version.ts index e156b0ea..0d43855f 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '5.0.0'; // x-release-please-version +export const VERSION = '5.1.0'; // x-release-please-version