Skip to content
Merged
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.3.0"
".": "0.4.0"
}
8 changes: 4 additions & 4 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
configured_endpoints: 19
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper%2Fbeeper-desktop-api-3f6555bfea11258c6e8882455360ae08202067a270313716ee15571b83ada577.yml
openapi_spec_hash: 020324a708981384284f8fad8ac8c66c
config_hash: 48ff2d23c2ebc82bd3c15787f0041684
configured_endpoints: 23
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper%2Fbeeper-desktop-api-4acef56b00be513f305543096fdd407e6947f0a5ad268ab2e627ff30b37a75db.yml
openapi_spec_hash: e876d796b6c25f18577f6be3944bf7d9
config_hash: 659111d4e28efa599b5f800619ed79c2
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
# Changelog

## 0.4.0 (2026-02-20)

Full Changelog: [v0.3.0...v0.4.0](https://github.com/beeper/desktop-api-go/compare/v0.3.0...v0.4.0)

### Features

* **api:** api update ([d93212e](https://github.com/beeper/desktop-api-go/commit/d93212edc1831f66dd2bdcf90f4b8129c0421561))
* **api:** api update ([090b9fa](https://github.com/beeper/desktop-api-go/commit/090b9fa8ed3a2bdeed47184d45ee55f3af920f1a))
* **api:** api update ([42ed730](https://github.com/beeper/desktop-api-go/commit/42ed7302937ab09fcf9c4137c292148ed5c27e4f))
* **api:** manual updates ([12bb117](https://github.com/beeper/desktop-api-go/commit/12bb11703a14d86f4b2d9f6c46a85b10349edaa9))
* **api:** manual updates ([bdbbdba](https://github.com/beeper/desktop-api-go/commit/bdbbdbab6e3ab56d5d259991c8ce0f7e35b8a729))


### Bug Fixes

* allow canceling a request while it is waiting to retry ([2c85b3b](https://github.com/beeper/desktop-api-go/commit/2c85b3bcc3fb6cc4cc4aeca6708a6642dc6c4586))


### Chores

* update mock server docs ([1c67766](https://github.com/beeper/desktop-api-go/commit/1c67766069b0a877174acdacb45ab88824038f9c))

## 0.3.0 (2026-02-13)

Full Changelog: [v0.2.1...v0.3.0](https://github.com/beeper/desktop-api-go/compare/v0.2.1...v0.3.0)
Expand Down
3 changes: 1 addition & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,7 @@ $ go mod edit -replace github.com/beeper/desktop-api-go=/path/to/desktop-api-go
Most tests require you to [set up a mock server](https://github.com/stoplightio/prism) against the OpenAPI spec to run the tests.

```sh
# you will need npm installed
$ npx prism mock path/to/your/openapi.yml
$ ./scripts/mock
```

```sh
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
The Beeper Desktop Go library provides convenient access to the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/)
from applications written in Go.

## MCP Server

Use 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.

[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40beeper%2Fdesktop-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBiZWVwZXIvZGVza3RvcC1tY3AiXSwiZW52Ijp7IkJFRVBFUl9BQ0NFU1NfVE9LRU4iOiJNeSBBY2Nlc3MgVG9rZW4ifX0)
[![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)

> Note: You may need to set environment variables in your MCP client.

## Installation

<!-- x-release-please-start-version -->
Expand All @@ -26,7 +35,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

```sh
go get -u 'github.com/beeper/desktop-api-go@v0.3.0'
go get -u 'github.com/beeper/desktop-api-go@v0.4.0'
```

<!-- x-release-please-end -->
Expand Down
5 changes: 0 additions & 5 deletions account.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,11 @@ func (r *AccountService) List(ctx context.Context, opts ...option.RequestOption)
type Account struct {
// Chat account added to Beeper. Use this to route account-scoped actions.
AccountID string `json:"accountID,required"`
// Display-only human-readable network name (e.g., 'WhatsApp', 'Messenger').
//
// Deprecated: deprecated
Network string `json:"network,required"`
// User the account belongs to.
User shared.User `json:"user,required"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
AccountID respjson.Field
Network respjson.Field
User respjson.Field
ExtraFields map[string]respjson.Field
raw string
Expand Down
62 changes: 62 additions & 0 deletions accountcontact.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/beeper/desktop-api-go/internal/apiquery"
"github.com/beeper/desktop-api-go/internal/requestconfig"
"github.com/beeper/desktop-api-go/option"
"github.com/beeper/desktop-api-go/packages/pagination"
"github.com/beeper/desktop-api-go/packages/param"
"github.com/beeper/desktop-api-go/packages/respjson"
"github.com/beeper/desktop-api-go/shared"
)
Expand All @@ -39,6 +41,33 @@ func NewAccountContactService(opts ...option.RequestOption) (r AccountContactSer
return
}

// List merged contacts for a specific account with cursor-based pagination.
func (r *AccountContactService) List(ctx context.Context, accountID string, query AccountContactListParams, opts ...option.RequestOption) (res *pagination.CursorSearch[shared.User], err error) {
var raw *http.Response
opts = slices.Concat(r.Options, opts)
opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
if accountID == "" {
err = errors.New("missing required accountID parameter")
return
}
path := fmt.Sprintf("v1/accounts/%s/contacts/list", accountID)
cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, query, &res, opts...)
if err != nil {
return nil, err
}
err = cfg.Execute()
if err != nil {
return nil, err
}
res.SetPageConfig(cfg, raw)
return res, nil
}

// List merged contacts for a specific account with cursor-based pagination.
func (r *AccountContactService) ListAutoPaging(ctx context.Context, accountID string, query AccountContactListParams, opts ...option.RequestOption) *pagination.CursorSearchAutoPager[shared.User] {
return pagination.NewCursorSearchAutoPager(r.List(ctx, accountID, query, opts...))
}

// Search contacts on a specific account using merged account contacts, network
// search, and exact identifier lookup.
func (r *AccountContactService) Search(ctx context.Context, accountID string, query AccountContactSearchParams, opts ...option.RequestOption) (res *AccountContactSearchResponse, err error) {
Expand Down Expand Up @@ -68,6 +97,39 @@ func (r *AccountContactSearchResponse) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

type AccountContactListParams struct {
// Opaque pagination cursor; do not inspect. Use together with 'direction'.
Cursor param.Opt[string] `query:"cursor,omitzero" json:"-"`
// Maximum contacts to return per page.
Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
// Optional search query for blended contact lookup.
Query param.Opt[string] `query:"query,omitzero" json:"-"`
// Pagination direction used with 'cursor': 'before' fetches older results, 'after'
// fetches newer results. Defaults to 'before' when only 'cursor' is provided.
//
// Any of "after", "before".
Direction AccountContactListParamsDirection `query:"direction,omitzero" json:"-"`
paramObj
}

// URLQuery serializes [AccountContactListParams]'s query parameters as
// `url.Values`.
func (r AccountContactListParams) URLQuery() (v url.Values, err error) {
return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
ArrayFormat: apiquery.ArrayQueryFormatRepeat,
NestedFormat: apiquery.NestedQueryFormatBrackets,
})
}

// Pagination direction used with 'cursor': 'before' fetches older results, 'after'
// fetches newer results. Defaults to 'before' when only 'cursor' is provided.
type AccountContactListParamsDirection string

const (
AccountContactListParamsDirectionAfter AccountContactListParamsDirection = "after"
AccountContactListParamsDirectionBefore AccountContactListParamsDirection = "before"
)

type AccountContactSearchParams struct {
// Text to search users by. Network-specific behavior.
Query string `query:"query,required" json:"-"`
Expand Down
31 changes: 31 additions & 0 deletions accountcontact_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,37 @@ import (
"github.com/beeper/desktop-api-go/option"
)

func TestAccountContactListWithOptionalParams(t *testing.T) {
baseURL := "http://localhost:4010"
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
baseURL = envURL
}
if !testutil.CheckTestServer(t, baseURL) {
return
}
client := beeperdesktopapi.NewClient(
option.WithBaseURL(baseURL),
option.WithAccessToken("My Access Token"),
)
_, err := client.Accounts.Contacts.List(
context.TODO(),
"accountID",
beeperdesktopapi.AccountContactListParams{
Cursor: beeperdesktopapi.String("1725489123456|c29tZUltc2dQYWdl"),
Direction: beeperdesktopapi.AccountContactListParamsDirectionBefore,
Limit: beeperdesktopapi.Int(1),
Query: beeperdesktopapi.String("x"),
},
)
if err != nil {
var apierr *beeperdesktopapi.Error
if errors.As(err, &apierr) {
t.Log(string(apierr.DumpRequest(true)))
}
t.Fatalf("err should be nil: %s", err.Error())
}
}

func TestAccountContactSearch(t *testing.T) {
baseURL := "http://localhost:4010"
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
Expand Down
25 changes: 25 additions & 0 deletions api.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Response Types:

Methods:

- <code title="get /v1/accounts/{accountID}/contacts/list">client.Accounts.Contacts.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AccountContactService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, accountID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AccountContactListParams">AccountContactListParams</a>) (\*<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go/packages/pagination">pagination</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go/packages/pagination#CursorSearch">CursorSearch</a>[<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go/shared#User">User</a>], <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="get /v1/accounts/{accountID}/contacts">client.Accounts.Contacts.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AccountContactService.Search">Search</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, accountID <a href="https://pkg.go.dev/builtin#string">string</a>, query <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AccountContactSearchParams">AccountContactSearchParams</a>) (\*<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AccountContactSearchResponse">AccountContactSearchResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

# Chats
Expand All @@ -60,6 +61,20 @@ Methods:
- <code title="post /v1/chats/{chatID}/reminders">client.Chats.Reminders.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatReminderService.New">New</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, chatID <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatReminderNewParams">ChatReminderNewParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="delete /v1/chats/{chatID}/reminders">client.Chats.Reminders.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatReminderService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, chatID <a href="https://pkg.go.dev/builtin#string">string</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>

## Messages

### Reactions

Response Types:

- <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatMessageReactionDeleteResponse">ChatMessageReactionDeleteResponse</a>
- <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatMessageReactionAddResponse">ChatMessageReactionAddResponse</a>

Methods:

- <code title="delete /v1/chats/{chatID}/messages/{messageID}/reactions">client.Chats.Messages.Reactions.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatMessageReactionService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, messageID <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatMessageReactionDeleteParams">ChatMessageReactionDeleteParams</a>) (\*<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatMessageReactionDeleteResponse">ChatMessageReactionDeleteResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /v1/chats/{chatID}/messages/{messageID}/reactions">client.Chats.Messages.Reactions.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatMessageReactionService.Add">Add</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, messageID <a href="https://pkg.go.dev/builtin#string">string</a>, params <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatMessageReactionAddParams">ChatMessageReactionAddParams</a>) (\*<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#ChatMessageReactionAddResponse">ChatMessageReactionAddResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

# Messages

Response Types:
Expand Down Expand Up @@ -88,3 +103,13 @@ Methods:
- <code title="get /v1/assets/serve">client.Assets.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AssetService.Serve">Serve</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AssetServeParams">AssetServeParams</a>) <a href="https://pkg.go.dev/builtin#error">error</a></code>
- <code title="post /v1/assets/upload">client.Assets.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AssetService.Upload">Upload</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AssetUploadParams">AssetUploadParams</a>) (\*<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AssetUploadResponse">AssetUploadResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /v1/assets/upload/base64">client.Assets.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AssetService.UploadBase64">UploadBase64</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, body <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AssetUploadBase64Params">AssetUploadBase64Params</a>) (\*<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#AssetUploadBase64Response">AssetUploadBase64Response</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

# Info

Response Types:

- <a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#InfoGetResponse">InfoGetResponse</a>

Methods:

- <code title="get /v1/info">client.Info.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#InfoService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (\*<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go">beeperdesktopapi</a>.<a href="https://pkg.go.dev/github.com/beeper/desktop-api-go#InfoGetResponse">InfoGetResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
Loading