TypeScript

Типизированный клиент для Pachca API. Работает в Node.js 18+ и в любом окружении с поддержкой fetch. ES Module с TypeScript-декларациями.

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

Установка

npm install @pachca/sdk

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

Получите API-токен в интерфейсе Пачки: Настройки → Автоматизации → API (подробнее — Авторизация).

import { PachcaClient } from "@pachca/sdk" const client = new PachcaClient("YOUR_TOKEN")

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

// Получение профиляconst response = client.profile.getProfile()// → User({ id: number, firstName: string, lastName: string, nickname: string, email: string, phoneNumber: string, department: string, title: string, role: UserRole, suspended: boolean, inviteStatus: InviteStatus, listTags: string[], customProperties: CustomProperty({ id: number, name: string, dataType: CustomPropertyDataType, value: string })[], userStatus: UserStatus({ emoji: string, title: string, expiresAt: string | null, isAway: boolean, awayMessage: UserStatusAwayMessage({ text: string }) | null }) | null, bot: boolean, sso: boolean, createdAt: string, lastActivityAt: string, timeZone: string, imageUrl: string | null })

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

import { PachcaClient } from "@pachca/sdk" // Стандартное подключениеconst client = new PachcaClient("YOUR_TOKEN") // С кастомным базовым URLconst client = new PachcaClient("YOUR_TOKEN", "https://custom-api.example.com/api/shared/v1")
ПараметрТипПо умолчаниюОписание
tokenstringBearer-токен для авторизации
baseUrlstringhttps://api.pachca.com/api/shared/v1Базовый URL API

Клиент не требует явного закрытия — все запросы используют глобальный fetch.

Все методы

МетодМетод API
client.common.requestExport()POSTЭкспорт сообщений
client.common.uploadFile()POSTЗагрузка файла
client.common.getUploadParams()POSTПолучение подписи, ключа и других параметров
client.common.downloadExport()GETСкачать архив экспорта
client.common.listProperties()GETСписок дополнительных полей
client.profile.getTokenInfo()GETИнформация о токене
client.profile.getProfile()GETИнформация о профиле
client.profile.getStatus()GETТекущий статус
client.profile.updateStatus()PUTНовый статус
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.updateUserStatus()PUTНовый статус сотрудника
client.users.deleteUser()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.chats.createChat()POSTНовый чат
client.chats.listChats()GETСписок чатов
client.chats.getChat()GETИнформация о чате
client.chats.updateChat()PUTОбновление чата
client.chats.archiveChat()PUTАрхивация чата
client.chats.unarchiveChat()PUTРазархивация чата
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.getThread()GETИнформация о треде
client.messages.createMessage()POSTНовое сообщение
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.linkPreviews.createLinkPreviews()POSTUnfurl (разворачивание ссылок)
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.views.openView()POSTОткрытие представления
client.bots.getWebhookEvents()GETИстория событий
client.bots.updateBot()PUTРедактирование бота
client.bots.deleteWebhookEvent()DELETEУдаление события
client.security.getAuditEvents()GETЖурнал аудита событий

Запросы

Все методы — асинхронные и возвращают Promise.

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

import { ChatAvailability, SortOrder } from "@pachca/sdk" // Список чатовconst response = client.chats.listChats({  sortId: SortOrder.Desc,  availability: ChatAvailability.IsMember,  lastMessageAtAfter: "2025-01-01T00:00:00.000Z",  lastMessageAtBefore: "2025-02-01T00:00:00.000Z",  personal: false,  limit: 1,  cursor: "eyJpZCI6MTAsImRpciI6ImFzYyJ9"})// → ListChatsResponse({ data: Chat[], meta?: PaginationMeta })

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

import { ChatCreateRequest, ChatCreateRequestChat } from "@pachca/sdk" // Создание чатаconst request: ChatCreateRequest = {  chat: {    name: "🤿 aqua",    memberIds: [123],    groupTagIds: [123],    channel: true,    public: false  }}const response = client.chats.createChat(request)// → Chat({ id: number, name: string, createdAt: string, ownerId: number, memberIds: number[], groupTagIds: number[], channel: boolean, personal: boolean, public: boolean, lastMessageAt: string, meetRoomUrl: string })

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

// Получение чатаconst response = client.chats.getChat(334)// → Chat({ id: number, name: string, createdAt: string, ownerId: number, memberIds: number[], groupTagIds: number[], channel: boolean, personal: boolean, public: boolean, lastMessageAt: string, meetRoomUrl: string })

Пагинация

Методы, возвращающие списки, используют cursor-based пагинацию. Ответ содержит поле meta.paginate.nextPage — курсор для следующей страницы.

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

let cursor: string | undefined do {  const response = await client.users.listUsers({ limit: 50, cursor })  for (const user of response.data) {    console.log(user.firstName, user.lastName)  }  cursor = response.meta?.paginate?.nextPage} while (cursor)

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

Для каждого метода с пагинацией есть *All() вариант, который автоматически обходит все страницы и возвращает плоский массив:

// Все пользователи одним массивомconst users = await client.users.listUsersAll()console.log(`Всего: ${users.length}`)

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

МетодВозвращает
security.getAuditEventsAll()AuditEvent[]
bots.getWebhookEventsAll()WebhookEvent[]
chats.listChatsAll()Chat[]
groupTags.listTagsAll()GroupTag[]
groupTags.getTagUsersAll()User[]
members.listMembersAll()User[]
messages.listChatMessagesAll()Message[]
reactions.listReactionsAll()Reaction[]
search.searchChatsAll()Chat[]
search.searchMessagesAll()Message[]
search.searchUsersAll()User[]
tasks.listTasksAll()Task[]
users.listUsersAll()User[]

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

SDK выбрасывает два типа ошибок:

ApiError

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

import { PachcaClient, ApiError } from "@pachca/sdk" try {  await client.chats.createChat(request)} catch (error) {  if (error instanceof ApiError) {    for (const e of error.errors) {      console.log(e.key, e.message)   // "name", "не может быть пустым"      console.log(e.code)             // "blank"    }  }}

Поля ApiErrorItem:

ПолеТипОписание
keystringПоле, вызвавшее ошибку
valuestring | nullПереданное значение
messagestringТекст ошибки
codeValidationErrorCodeКод валидации (blank, invalid, taken, ...)
payloadstring | nullДополнительные данные

OAuthError

Возникает при ошибке авторизации (401):

import { OAuthError } from "@pachca/sdk" try {  await client.profile.getProfile()} catch (error) {  if (error instanceof OAuthError) {    console.log(error.message) // "Token not found"  }}

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

SDK автоматически повторяет запрос при получении 429 Too Many Requests:

  • До 3 повторов на каждый запрос
  • Если сервер вернул заголовок Retry-After — ждёт указанное время
  • Иначе — экспоненциальный backoff: 1 сек, 2 сек, 4 сек
  • Все остальные ошибки возвращаются сразу без retry

Сериализация

SDK автоматически конвертирует имена полей между camelCase (TypeScript) и snake_case (API):

// Вы пишете:{ memberIds: [123], groupTagIds: [456] } // SDK отправляет:{ "member_ids": [123], "group_tag_ids": [456] } // API возвращает:{ "last_message_at": "2025-01-01T00:00:00Z" } // Вы получаете:{ lastMessageAt: "2025-01-01T00:00:00Z" }

Типы

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

import {  // Модели  Chat, Message, User, Task, GroupTag, Thread, Reaction,  // Запросы  ChatCreateRequest, MessageCreateRequest, TaskCreateRequest,  // Параметры  ListChatsParams, ListUsersParams, SearchMessagesParams,  // Ответы  ListChatsResponse, ListMembersResponse,  // Перечисления  AuditEventKey, ChatAvailability, ChatMemberRole, ChatMemberRoleFilter,  ChatSubtype, CustomPropertyDataType, FileType, InviteStatus,  MemberEventType, MessageEntityType, OAuthScope, ReactionEventType,  SearchEntityType, SearchSortOrder, SortOrder, TaskKind, TaskStatus,  UserEventType, UserRole, ValidationErrorCode, WebhookEventType,  // Ошибки  ApiError, OAuthError,} from "@pachca/sdk"

Примеры

import { Button, FileType, MessageCreateRequest, MessageCreateRequestFile, MessageCreateRequestMessage, MessageEntityType, PachcaClient, TaskCreateRequest, TaskCreateRequestCustomProperty, TaskCreateRequestTask, TaskKind } from "@pachca/sdk" const client = new PachcaClient("YOUR_TOKEN") // Отправка сообщенияconst request: MessageCreateRequest = {  message: {    entityType: MessageEntityType.Discussion,    entityId: 334,    content: "Вчера мы продали 756 футболок (что на 10% больше, чем в прошлое воскресенье)",    files: [{      key: "attaches/files/93746/e354fd79-4f3e-4b5a-9c8d-1a2b3c4d5e6f/logo.png",      name: "logo.png",      fileType: FileType.Image,      size: 12345,      width: 800,      height: 600    }],    buttons: [[{      text: "Подробнее",      url: "https://example.com/details",      data: "awesome"    }]],    parentMessageId: 194270,    displayAvatarUrl: "https://example.com/avatar.png",    displayName: "Бот Поддержки",    skipInviteMentions: false,    linkPreview: false  }}const response = client.messages.createMessage(request)// → Message({ id: number, entityType: MessageEntityType, entityId: number, chatId: number, rootChatId: number, content: string, userId: number, createdAt: string, url: string, files: File({ id: number, key: string, name: string, fileType: FileType, url: string, width?: number | null, height?: number | null })[], buttons: Button({ text: string, url?: string, data?: string })[][] | null, thread: Thread({ id: number, chatId: number, messageId: number, messageChatId: number, updatedAt: string }) | null, forwarding: Forwarding({ originalMessageId: number, originalChatId: number, authorId: number, originalCreatedAt: string, originalThreadId: number | null, originalThreadMessageId: number | null, originalThreadParentChatId: number | null }) | null, parentMessageId: number | null, displayAvatarUrl: string | null, displayName: string | null, changedAt: string | null, deletedAt: string | null }) // Список сотрудниковconst response = client.users.listUsers({  query: "Олег",  limit: 1,  cursor: "eyJpZCI6MTAsImRpciI6ImFzYyJ9"})// → ListUsersResponse({ data: User[], meta?: PaginationMeta }) // Создание задачиconst request: TaskCreateRequest = {  task: {    kind: TaskKind.Reminder,    content: "Забрать со склада 21 заказ",    dueAt: "2020-06-05T12:00:00.000+03:00",    priority: 2,    performerIds: [123],    chatId: 456,    allDay: false,    customProperties: [{ id: 78, value: "Синий склад" }]  }}const response = client.tasks.createTask(request)// → Task({ id: number, kind: TaskKind, content: string, dueAt: string | null, priority: number, userId: number, chatId: number | null, status: TaskStatus, createdAt: string, performerIds: number[], allDay: boolean, customProperties: CustomProperty({ id: number, name: string, dataType: CustomPropertyDataType, value: string })[] })