Для разработчиков

Go

Типизированный клиент для Pachca API на Go. Синхронный, с контекстами (context.Context), автопагинацией и обработкой retry. Требуется Go 1.24+.

Быстрый старт

Установка

go get github.com/pachca/openapi/sdk/go/generated

Создание клиента

Клиенту нужен токен бота или персональный токен. Какой выбрать и кто может его выпустить, описано в разделе Какой токен выбрать.

import (	"context" 	pachca "github.com/pachca/openapi/sdk/go/generated") client := pachca.NewPachcaClient("YOUR_TOKEN")ctx := context.Background()

Первый запрос

import pachca "github.com/pachca/openapi/sdk/go/generated" // Получение профиляresponse, err := client.Profile.GetProfile(ctx)// → User{ID: int32, FirstName: *string, LastName: *string, Nickname: string, Email: *string, PhoneNumber: *string, Department: *string, Title: *string, Role: UserRole, Suspended: bool, InviteStatus: InviteStatus, InviterID: *int32, ListTags: []string, CustomProperties: []CustomProperty{ID: int32, Name: string, DataType: CustomPropertyDataType, Value: *string}, UserStatus: *UserStatus{Emoji: string, Title: string, ExpiresAt: *string, IsAway: bool, AwayMessage: *UserStatusAwayMessage{Text: string}}, Bot: bool, Sso: bool, CreatedAt: time.Time, LastActivityAt: *string, TimeZone: *string, ImageURL: *string}

Инициализация

import pachca "github.com/pachca/openapi/sdk/go/generated" // Стандартное подключениеclient := pachca.NewPachcaClient("YOUR_TOKEN") // С кастомным базовым URLclient := pachca.NewPachcaClient("YOUR_TOKEN", pachca.WithBaseURL("https://custom-api.example.com/api/shared/v1"))
ПараметрТипПо умолчаниюОписание
tokenstring—Bearer-токен для авторизации
opts...ClientOption—Необязательные настройки. pachca.WithBaseURL(url) меняет базовый URL API, по умолчанию https://api.pachca.com/api/shared/v1.

Все методы принимают context.Context первым аргументом — используйте его для таймаутов и отмены:

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)defer cancel() user, err := client.Profile.GetProfile(ctx)

Все методы

МетодМетод API
client.Oauth.RevokeToken()POSTОтзыв токена
client.Oauth.ExchangeToken()POSTОбмен кода на токен
client.Oauth.GetTokenInfo()GETИнформация о токене
client.Chats.CreateChat()POSTНовый чат
client.Chats.RequestExport()POSTЭкспорт сообщений
client.Chats.ListChats()GETСписок чатов
client.Chats.DownloadExport()GETСкачать архив экспорта
client.Chats.GetChat()GETИнформация о чате
client.Chats.ListCompanyChats()GETСписок чатов пространства
client.Chats.UpdateChat()PUTРедактирование чата
client.Chats.ArchiveChat()PUTАрхивация чата
client.Chats.UpdateChatAvatar()PUTЗагрузка аватара чата
client.Chats.UnarchiveChat()PUTРазархивация чата
client.Chats.MarkChatUnread()PUTОтметка чата непрочитанным
client.Chats.DeleteChatAvatar()DELETEУдаление аватара чата
client.Profile.GetProfile()GETСвой профиль
client.Profile.GetStatus()GETСвой статус
client.Profile.UpdateProfileAvatar()PUTЗагрузка своего аватара
client.Profile.UpdateStatus()PUTНовый свой статус
client.Profile.DeleteProfileAvatar()DELETEУдаление своего аватара
client.Profile.DeleteStatus()DELETEУдаление своего статуса
client.Users.CreateUser()POSTНовый сотрудник
client.Users.ListUsers()GETСписок сотрудников
client.Users.GetUser()GETИнформация о сотруднике
client.Users.GetUserStatus()GETСтатус сотрудника
client.Users.UpdateUser()PUTРедактирование сотрудника
client.Users.UpdateUserAvatar()PUTЗагрузка аватара сотрудника
client.Users.UpdateUserStatus()PUTНовый статус сотрудника
client.Users.DeleteUser()DELETEУдаление сотрудника
client.Users.DeleteUserAvatar()DELETEУдаление аватара сотрудника
client.Users.DeleteUserStatus()DELETEУдаление статуса сотрудника
client.GroupTags.CreateTag()POSTНовый тег
client.GroupTags.ListTags()GETСписок тегов
client.GroupTags.GetTag()GETИнформация о теге
client.GroupTags.GetTagUsers()GETСписок сотрудников тега
client.GroupTags.UpdateTag()PUTРедактирование тега
client.GroupTags.DeleteTag()DELETEУдаление тега
client.Members.AddTags()POSTДобавление тегов
client.Members.AddMembers()POSTДобавление участников
client.Members.ListMembers()GETСписок участников чата
client.Members.UpdateMemberRole()PUTРедактирование роли участника
client.Members.RemoveTag()DELETEИсключение тега из чата
client.Members.LeaveChat()DELETEВыход из чата
client.Members.RemoveMember()DELETEИсключение участника
client.Threads.CreateThread()POSTНовый тред
client.Threads.CreateStandaloneThread()POSTНовый самостоятельный тред
client.Threads.ListThreads()GETСписок тредов
client.Threads.GetThread()GETИнформация о треде
client.Messages.CreateMessage()POSTНовое сообщение
client.Messages.Unfurl()POSTUnfurl (разворачивание ссылок)
client.Messages.PinMessage()POSTЗакрепление сообщения
client.Messages.ListChatMessages()GETСписок сообщений чата
client.Messages.GetMessage()GETИнформация о сообщении
client.Messages.UpdateMessage()PUTРедактирование сообщения
client.Messages.DeleteMessage()DELETEУдаление сообщения
client.Messages.UnpinMessage()DELETEОткрепление сообщения
client.ReadMembers.ListReadMembers()GETСписок прочитавших сообщение
client.Reactions.AddReaction()POSTДобавление реакции
client.Reactions.ListReactions()GETСписок реакций
client.Reactions.RemoveReaction()DELETEУдаление реакции
client.ImportantMessages.AddMessageToImportant()POSTДобавление сообщения в важные
client.ImportantMessages.ListImportantMessages()GETСписок важных сообщений
client.ImportantMessages.RemoveMessageFromImportant()DELETEУдаление сообщения из важных
client.Search.SearchChats()GETПоиск чатов
client.Search.SearchMessages()GETПоиск сообщений
client.Search.SearchUsers()GETПоиск сотрудников
client.Tasks.CreateTask()POSTНовое напоминание
client.Tasks.ListTasks()GETСписок напоминаний
client.Tasks.GetTask()GETИнформация о напоминании
client.Tasks.UpdateTask()PUTРедактирование напоминания
client.Tasks.DeleteTask()DELETEУдаление напоминания
client.Drafts.CreateDraft()POSTНовый черновик
client.Drafts.ListDrafts()GETСписок черновиков
client.Drafts.GetDraft()GETИнформация о черновике
client.Drafts.UpdateDraft()PUTРедактирование черновика
client.Drafts.DeleteDraft()DELETEУдаление черновика
client.Views.OpenView()POSTОткрытие представления
client.Views.SubmitViewResponse()POSTОтвет на отправку формы
client.Bots.SelfRecreateBotToken()POSTРотация собственного токена бота
client.Bots.CreateBot()POSTНовый бот
client.Bots.RecreateBotToken()POSTРотация токена бота
client.Bots.RotateBotClientSecret()POSTРотация секрета клиента
client.Bots.CreateBotToken()POSTНовый токен бота
client.Bots.ReissueBotToken()POSTПеревыпуск токена бота
client.Bots.ListBots()GETСписок ботов
client.Bots.GetBot()GETИнформация о боте
client.Bots.GetBotScopes()GETКаталог прав бота
client.Bots.ListBotTokens()GETСписок токенов бота
client.Bots.ListCompanyBots()GETСписок ботов пространства
client.Bots.GetWebhookEvents()GETИстория событий
client.Bots.GetWebhookEventsStream()GETПоток событий
client.Bots.SelfUpdateBotWebhook()PUTСаморегистрация вебхука бота
client.Bots.UpdateBot()PUTРедактирование бота
client.Bots.UpdateBotAvatar()PUTЗагрузка аватара бота
client.Bots.UpdateBotToken()PUTИзменение токена бота
client.Bots.DeleteBot()DELETEУдаление бота
client.Bots.DeleteBotAvatar()DELETEУдаление аватара бота
client.Bots.DeleteBotToken()DELETEУдаление токена бота
client.Bots.DeleteWebhookEvent()DELETEУдаление события истории
client.Security.GetAuditEvents()GETЖурнал аудита событий
client.CustomProperties.ListProperties()GETСписок дополнительных полей
client.Files.UploadFile()POSTЗагрузка файла
client.Files.GetUploadParams()POSTПолучение подписи, ключа и других параметров
client.Files.DownloadFile()GETСкачивание файла

Запросы

Все методы — синхронные и возвращают (*T, error).

GET с параметрами:

import (	"time" 	pachca "github.com/pachca/openapi/sdk/go/generated") // Список чатовparams := &pachca.ListChatsParams{	Sort: pachca.Ptr(pachca.ChatSortFieldID),	Order: pachca.Ptr(pachca.SortOrderDesc),	Availability: pachca.Ptr(pachca.ChatAvailabilityIsMember),	Archived: pachca.Ptr(true),	LastMessageAtAfter: pachca.Ptr(time.Date(2025, 1, 1, 0, 0, 0, 0, time.UTC)),	LastMessageAtBefore: pachca.Ptr(time.Date(2025, 2, 1, 0, 0, 0, 0, time.UTC)),	Personal: pachca.Ptr(false),	Limit: pachca.Ptr(int32(1)),	Cursor: pachca.Ptr("eyJpZCI6MTAsImRpciI6ImFzYyJ9"),}response, err := client.Chats.ListChats(ctx, params)// → ListChatsResponse{Data: []Chat, Meta: PaginationMeta}

POST с телом запроса:

import pachca "github.com/pachca/openapi/sdk/go/generated" // Создание чатаrequest := pachca.ChatCreateRequest{	Chat: pachca.ChatCreateRequestChat{		Name: "🤿 aqua",		MemberIDs: []int32{int32(123)},		GroupTagIDs: []int32{int32(123)},		Channel: pachca.Ptr(true),		Public: pachca.Ptr(false),	},}response, err := client.Chats.CreateChat(ctx, request)// → CreateChatResponse{Data: Chat{ID: int32, Name: string, CreatedAt: time.Time, OwnerID: int32, MemberIDs: []int32, GroupTagIDs: []int32, Channel: bool, Archived: bool, Personal: bool, Public: bool, LastMessageAt: time.Time, MeetRoomURL: string, AvatarURL: *string}, Meta: CreateChatResponseMeta{NotFoundMemberIDs: []int32, NotFoundGroupTagIDs: []int32}}

Простой вызов по ID:

import pachca "github.com/pachca/openapi/sdk/go/generated" // Получение чатаresponse, err := client.Chats.GetChat(ctx, int32(334))// → Chat{ID: int32, Name: string, CreatedAt: time.Time, OwnerID: int32, MemberIDs: []int32, GroupTagIDs: []int32, Channel: bool, Archived: bool, Personal: bool, Public: bool, LastMessageAt: time.Time, MeetRoomURL: string, AvatarURL: *string}

Указатели для необязательных полей

Для необязательных полей используйте функцию Ptr():

request := pachca.ChatUpdateRequest{    Chat: pachca.ChatUpdateRequestChat{        Name:   pachca.Ptr("Новое название"),        Public: pachca.Ptr(true),    },}

Поле, которое не задано, в запрос не попадает, поэтому метод обновления меняет только то, что вы передали.

Значение null

Некоторые поля API принимают null: например, null в oauth_client выключает у бота авторизацию от имени сотрудника, а в webhook.kind удаляет входящий вебхук. Чтобы отправить null, назовите поле в NullFields той же модели запроса так, как оно называется в Go:

request := pachca.BotUpdateRequest{    Webhook: &pachca.BotUpdateRequestWebhook{        NullFields: []string{"Kind"},    },}

NullFields есть у моделей запроса с такими полями, а в комментарии к нему перечислены имена, которые в нём можно указать. С другим именем SDK возвращает ошибку и запрос не отправляет.

Пагинация

Поля пагинации называются как в API, но в PascalCase: Meta.Paginate.NextPage, PrevPage, HasNext и HasPrev, а у методов поиска ещё Meta.Total. Необязательные поля, в том числе HasNext, приходят указателями. Какие поля приходят у каждого метода и как понять, что страницы закончились, описано в разделе Пагинация.

Ручная пагинация

var cursor *stringfor {    params := &pachca.ListChatsParams{Limit: pachca.Ptr(int32(50)), Cursor: cursor}    response, err := client.Chats.ListChats(ctx, params)    if err != nil {        log.Fatal(err)    }    if len(response.Data) == 0 {        break    }    for _, chat := range response.Data {        fmt.Println(chat.ID, chat.Name)    }    if hasNext := response.Meta.Paginate.HasNext; hasNext != nil && !*hasNext {        break    }    cursor = pachca.Ptr(response.Meta.Paginate.NextPage)}

Цикл заканчивается на HasNext, равном false, или на пустой странице. Так же обходят страницы методы *All().

Автопагинация

Для каждого метода с пагинацией есть *All() вариант:

// Все чаты одним слайсомchats, err := client.Chats.ListChatsAll(ctx, nil)if err != nil {    log.Fatal(err)}fmt.Printf("Всего: %d\n", len(chats))

Доступные методы автопагинации:

МетодВозвращает
Security.GetAuditEventsAll()[]AuditEvent
Bots.ListBotsAll()[]BotResponse
Bots.ListBotTokensAll()[]BotAccessToken
Bots.ListCompanyBotsAll()[]CompanyBotResponse
Bots.GetWebhookEventsAll()[]WebhookEvent
Chats.ListChatsAll()[]Chat
Chats.ListCompanyChatsAll()[]Chat
Drafts.ListDraftsAll()[]Draft
GroupTags.ListTagsAll()[]GroupTag
GroupTags.GetTagUsersAll()[]User
ImportantMessages.ListImportantMessagesAll()[]Message
Members.ListMembersAll()[]User
Messages.ListChatMessagesAll()[]Message
Reactions.ListReactionsAll()[]Reaction
Search.SearchChatsAll()[]Chat
Search.SearchMessagesAll()[]Message
Search.SearchUsersAll()[]User
Tasks.ListTasksAll()[]Task
Threads.ListThreadsAll()[]Thread
Users.ListUsersAll()[]User

Обработка ошибок

SDK возвращает два типа ошибок (реализуют интерфейс error):

ApiError

Возникает при ошибках 400, 403, 404, 409, 410, 422 с массивом errors в теле:

_, err := client.Chats.CreateChat(ctx, request)if err != nil {    var apiErr *pachca.ApiError    if errors.As(err, &apiErr) {        for _, e := range apiErr.Errors {            fmt.Println(e.Key, e.Message)   // name не может быть пустым            fmt.Println(e.Code)             // blank        }    }}

Поля ApiErrorItem:

ПолеТипОписание
KeystringПоле, вызвавшее ошибку
ValueanyПереданное значение
MessagestringТекст ошибки
CodeValidationErrorCodeКод валидации
Payloadmap[string]anyДополнительные данные

Код статуса ответа — в поле StatusCode. Если ответ с ошибкой пришёл без тела или не в JSON, SDK тоже возвращает *ApiError: с кодом статуса и пустым Errors. Так бывает с ответом 404 без тела от метода GETПоток событий, когда история событий выключена, и со страницей прокси при 502.

OAuthError

Возникает при ошибке авторизации: 401, а также 403 с кодом insufficient_scope или role_forbidden и отказе при обмене кода на токен. Код — в поле error, список кодов — в разделе Ошибки авторизации:

user, err := client.Profile.GetProfile(ctx)if err != nil {    var oauthErr *pachca.OAuthError    if errors.As(err, &oauthErr) {        fmt.Println(oauthErr.Err)              // "insufficient_scope"        fmt.Println(oauthErr.ErrorDescription)  // описание ошибки    }}

Поле Err — перечисление OAuthErrorCode: его сравнивают с константой, например pachca.OAuthErrorCodeInsufficientScope, а строкой оно становится через string(oauthErr.Err). Если у ответа 401 нет тела в формате OAuth, SDK возвращает *ApiError с кодом статуса 401.

Повторные запросы

Паузы между попытками, к каждой SDK добавляет случайную величину до 25%:

  • 429 с заголовком Retry-After: срок из заголовка
  • 429 без заголовка: 1 сек, 2 сек, 4 сек
  • 5xx: ~10 сек, ~20 сек, ~40 сек

Сетевую ошибку без ответа сервера SDK не повторяет и сразу возвращает её из метода. Тело запроса для каждой попытки SDK создаёт заново через req.GetBody().

Общие правила повторов — в разделе Повторные запросы.

Типы

Все типы экспортируются из пакета:

import pachca "github.com/pachca/openapi/sdk/go/generated" // Моделиvar chat pachca.Chatvar msg  pachca.Messagevar user pachca.User // Запросыvar req pachca.ChatCreateRequest // Перечисленияkey := pachca.AuditEventKeyUserLoginavailability := pachca.ChatAvailabilityPublicrole := pachca.ChatMemberRoleAdminstatus := pachca.TaskStatusDone // Ошибкиvar apiErr *pachca.ApiErrorvar oauthErr *pachca.OAuthError

Перечисление — строковый тип, поэтому значение, которого SDK ещё не знает, приходит в ответе как есть.

Все перечисления SDK: AuditEventKey, AuditLoginGrantDenyReason, AuditLoginGrantDevicePlatform, BotCanEdit, BotEventName, BotTemplateEngine, BotTriggerOn, BotWebhookKind, BotWhoCanAdd, ChatActivity, ChatAvailability, ChatMemberRole, ChatMemberRoleFilter, ChatSortField, ChatSubtype, CustomPropertyDataType, DraftRepetitionInterval, DraftType, FileTarget, FileType, InviteStatus, MemberEventType, MessageEntityType, MessageSearchSort, MessageSortField, OAuthErrorCode, OAuthScope, OAuthTokenTypeHint, ReactionEventType, SearchEntityType, SearchSortOrder, SortOrder, TaskKind, TaskStatus, UserCreateRole, UserEventType, UserRole, UserRoleInput, ValidationErrorCode, VideoCallEventType, VoiceTranscriptStatus и WebhookEventType.

Тело вебхука

Тела событий вебхука описаны типами MessageWebhookPayload, ReactionWebhookPayload, ButtonWebhookPayload, ViewSubmitWebhookPayload, ChatMemberWebhookPayload, CompanyMemberWebhookPayload, LinkSharedWebhookPayload и VideoCallWebhookPayload. Тип WebhookPayloadUnion объединяет их: при разборе JSON он выбирает тип по полям type и event и заполняет одно поле-указатель.

// body — тело запроса в байтахvar payload pachca.WebhookPayloadUnionif err := json.Unmarshal(body, &payload); err != nil {    log.Fatal(err)}if button := payload.ButtonWebhookPayload; button != nil {    fmt.Println(button.MessageID, button.Data)}

Подпись проверяйте по исходному телу до разбора, как в разделе Безопасность. Те же типы отдают методы PollWebhookEvents и PollWebhookPayloads, которые забирают события из истории: пример — в разделе Пример поллинга.

Примеры

Отправка сообщения:

import (	"context" 	pachca "github.com/pachca/openapi/sdk/go/generated") client := pachca.NewPachcaClient("YOUR_TOKEN")ctx := context.Background() request := pachca.MessageCreateRequest{	Message: pachca.MessageCreateRequestMessage{		EntityID: int32(334),		Content: pachca.Ptr("Вчера мы продали 756 футболок (что на 10% больше, чем в прошлое воскресенье)"),	},}response, err := client.Messages.CreateMessage(ctx, request)// → Message{ID: int32, EntityType: MessageEntityType, EntityID: int32, ChatID: int32, RootChatID: int32, Content: string, UserID: int32, CreatedAt: time.Time, URL: string, Files: []File{ID: int32, Key: string, Name: string, FileType: FileType, URL: string, Width: *int32, Height: *int32, DurationMs: *int32}, VoiceContent: *VoiceContent{DurationMs: int32, Waveform: string, Transcript: *string, TranscriptStatus: *VoiceTranscriptStatus}, Buttons: *[][]Button{Text: string, URL: *string, Data: *string}, Thread: *MessageThread{ID: int64, ChatID: int64}, Forwarding: *Forwarding{OriginalMessageID: int32, OriginalChatID: int32, AuthorID: int32, OriginalCreatedAt: time.Time, OriginalThreadID: *int32, OriginalThreadMessageID: *int32, OriginalThreadParentChatID: *int32}, ParentMessageID: *int32, DisplayAvatarURL: *string, DisplayName: *string, ChangedAt: *string, DeletedAt: *string, Important: bool}

Список сотрудников:

import (	"context" 	pachca "github.com/pachca/openapi/sdk/go/generated") client := pachca.NewPachcaClient("YOUR_TOKEN")ctx := context.Background() params := &pachca.ListUsersParams{	Query: pachca.Ptr("Олег"),	Limit: pachca.Ptr(int32(1)),	Cursor: pachca.Ptr("eyJpZCI6MTAsImRpciI6ImFzYyJ9"),}response, err := client.Users.ListUsers(ctx, params)// → ListUsersResponse{Data: []User, Meta: PaginationMeta}

Создание напоминания:

import (	"context"	"time" 	pachca "github.com/pachca/openapi/sdk/go/generated") client := pachca.NewPachcaClient("YOUR_TOKEN")ctx := context.Background() request := pachca.TaskCreateRequest{	Task: pachca.TaskCreateRequestTask{		Kind: pachca.Ptr(pachca.TaskKindReminder),		Content: pachca.Ptr("Забрать со склада 21 заказ"),		DueAt: pachca.Ptr(time.Date(2020, 6, 5, 12, 0, 0, 0, time.FixedZone("", 3*60*60))),		Priority: pachca.Ptr(int32(2)),		PerformerIDs: []int32{int32(123)},		ChatID: pachca.Ptr(int32(456)),		AllDay: pachca.Ptr(false),		CustomProperties: []pachca.TaskCreateRequestCustomProperty{pachca.TaskCreateRequestCustomProperty{			ID: int32(78),			Value: "Синий склад",		}},	},}response, err := client.Tasks.CreateTask(ctx, request)// → Task{ID: int32, Kind: TaskKind, Content: string, DueAt: *string, Priority: int32, UserID: int32, ChatID: *int32, Status: TaskStatus, CreatedAt: time.Time, PerformerIDs: []int32, AllDay: bool, CustomProperties: []CustomProperty{ID: int32, Name: string, DataType: CustomPropertyDataType, Value: *string}}