Представляем SDK SupDesk

SupDesk Team

Каждый серьёзный продукт рано или поздно пишет слой интеграции — скрипт, читающий из почтового ящика, задачу cron, синхронизирующую доску, или эндпоинт, принимающий обратную связь из вашего собственного интерфейса. Консоль SupDesk отлична, пока вы сидите за клавиатурой. Но как только требуется автоматизация, вам нужен API, а API хорош ровно настолько, насколько хороши клиенты для работы с ним.

Сегодня мы выпускаем четыре таких клиента.

Знакомьтесь с SDK

  • JavaScript / TypeScriptsupdesk в npm. Работает без изменений в Node 18+, Deno, Bun и Cloudflare Workers, не имея сторонних рантайм-зависимостей.
  • Pythonsupdesk в PyPI. Один синхронный клиент SupDesk и один асинхронный клиент AsyncSupDesk, использующие единое ядро на базе httpx.
  • Gogithub.com/rabinapps/supdesk-go. Использует только стандартную библиотеку, поэтому собирается везде, где работает Go 1.23+, включая Cloudflare Workers через GOOS=wasip1.
  • Dartsupdesk в pub.dev. Построен на базе dio, поэтому перехватчики, CancelToken и адаптеры прокси работают привычным образом.

Установка

npm install supdesk
pip install supdesk
go get github.com/rabinapps/supdesk-go
dependencies:
  supdesk: ^0.1.0

Один API, четыре языка

Наши SDK — это не четыре изолированные обёртки, а один и тот же API с одинаковой семантикой на всех языках. Если вы научились читать обращения на одном из них, вы сможете делать это на всех четырёх.

Автопагинация. Метод list() возвращает страницу, которая одновременно является асинхронным итерируемым объектом — перебирайте все страницы через for await или запрашивайте только первую, если этого достаточно.

Типизированные ресурсы. Обращения, обратная связь, записи журнала изменений, сообщения, заявки в список ожидания, бета-программы и тестировщики, а также статьи и категории центра помощи — каждый ресурс оснащён ожидаемыми методами и типизированными параметрами, благодаря чему опечатки отлавливаются на этапе компиляции, а не в продакшене.

Типизированные ошибки. Все сбои наследуются от единого базового класса — SupDeskError в JS и Python, APIError в Go, SupDeskException в Dart — поэтому один блок catch обрабатывает всё, пока instanceof или errors.As сужают тип до конкретного случая.

Вебхуки. constructEventFromRequest, construct_event_from_headers, ConstructEvent и constructEventFromHeaders проверяют подпись SupDesk за константное время, чтобы вы могли доверять входящим данным.

Встроенная отказоустойчивость. Каждый клиент выполняет повторные попытки с экспоненциальной задержкой и джиттером, учитывает заголовок Retry-After и никогда не повторяет платный POST-запрос, который мог быть уже принят — нестабильная сеть не приведёт к дублированию тикета пользователя.

Серверное применение по проекту

Ключи API SupDesk авторизуют доступ от имени всего вашего проекта, поэтому SDK отказываются работать в браузере — конструкторы JS и Dart выбрасывают исключение при обнаружении DOM или клиентской сборки, а в файлах README четко объяснена причина. Храните ключ в серверных переменных окружения за контролируемым вами эндпоинтом.

Ещё две важные детали: чтение доступно на всех тарифах, тогда как запись (POST/PATCH/DELETE) требует платного тарифа; кроме того, ключи ограничены рамками проекта, поэтому выдавайте каждому окружению свой ключ, чтобы иметь возможность отозвать один без вреда для остальных.

Где применяется SupDesk

Эти SDK составляют серверную часть руководства по интеграции SupDesk в SaaS — мультитенантная поддержка, доступ к API и вебхуки для продуктов, желающих встроить поддержку в собственные системы. Полный справочник доступен в документации API.

Как начать

Получите API-ключ в разделе Настройки рабочего пространства → Ключи API, установите клиент для вашего стека и выполните быстрый старт с этой страницы. Затем клонируйте репозиторий и прочитайте README.

Начать на supdesk.app

Серверные SDK для интеграции с бэкендом

Живые примеры кода, загружаемые из репозитория GitHub каждого SDK.

RabinApps/supdesk-nodeJavaScript / TypeScript
import { SupDesk } from "supdesk";

const supdesk = new SupDesk({ apiKey: process.env.SUPDESK_API_KEY! });

// Auto-pages: iterating walks every page for you.
for await (const submission of await supdesk.submissions.list({
  status: "open",
})) {
  console.log(submission.title);
}

await supdesk.submissions.create({
  type: "bug",
  title: "Export button does nothing",
  email: "user@example.com",
  body: "Clicking Export on the reports page has no effect.",
});
RabinApps/supdesk-pythonPython
from supdesk import SupDesk

supdesk = SupDesk()  # api_key=... or $SUPDESK_API_KEY

# Auto-pages: iterating walks every page for you.
for submission in supdesk.submissions.list(status="open"):
    print(submission.title)

supdesk.submissions.create(
    type="bug",
    title="Export button does nothing",
    email="user@example.com",
    body="Clicking Export on the reports page has no effect.",
)
RabinApps/supdesk-goGo
import "github.com/rabinapps/supdesk-go/supdesk"

client, err := supdesk.New(os.Getenv("SUPDESK_API_KEY"))
if err != nil {
    log.Fatal(err)
}

page, err := client.Submissions.List(ctx, supdesk.SubmissionsListParams{
    Status: ptr("open"),
})
if err != nil {
    return err
}
// Auto-pages: All walks every page for you.
for sub, err := range page.All(ctx) {
    if err != nil {
        return err
    }
    fmt.Println(sub.Title)
}

_, err = client.Submissions.Create(ctx, supdesk.SubmissionsCreateParams{
    Type:  supdesk.SubmissionTypeBug,
    Title: "Export button does nothing",
    Email: "user@example.com",
    Body:  "Clicking Export on the reports page has no effect.",
})
RabinApps/supdesk-dartDart
import 'dart:io';
import 'package:supdesk/supdesk.dart';

final supdesk = SupDesk(apiKey: Platform.environment['SUPDESK_API_KEY']!);

// Auto-pages: the stream walks every page for you.
final page = await supdesk.submissions.list(status: PostStatus.open);
await for (final submission in page.autoPaging()) {
  print(submission.title);
}

await supdesk.submissions.create(
  type: SubmissionType.bug,
  title: 'Export button does nothing',
  email: 'user@example.com',
  body: 'Clicking Export on the reports page has no effect.',
);

Теги

#sdk#api#developers