Skip to main content

Pachca Python SDK

Python клиент для Pachca API.

Установка

pip install pachca-sdk

Использование

from pachca.client import PachcaClient
from pachca.models import (
    ListChatMessagesParams,
    MessageCreateRequest,
    MessageCreateRequestMessage,
    ReactionRequest,
)

client = PachcaClient("YOUR_TOKEN")

# Отправка сообщения
message = await client.messages.create_message(
    MessageCreateRequest(message=MessageCreateRequestMessage(entity_id=chat_id, content="Привет из Python SDK!"))
)

# Получение сообщения
fetched = await client.messages.get_message(message.id)

# Реакция
await client.reactions.add_reaction(message.id, ReactionRequest(code="👀"))

# Закрепление
await client.messages.pin_message(message.id)

# Страница сообщений чата и курсор следующей страницы
page = await client.messages.list_chat_messages(ListChatMessagesParams(chat_id=chat_id))
print(page.meta.paginate.next_page)

await client.close()

Все методы асинхронные: вызывайте их через await внутри async def.

Конвенции

  • Вход: path-параметры передаются аргументами метода. Тело из одного обязательного поля, например роль участника чата, тоже разворачивается в аргумент. Остальные тела передаются одним объектом-запросом, query-параметры — объектом *Params.
  • Выход: если ответ API содержит единственное поле data, SDK возвращает его содержимое напрямую. Если рядом с data есть meta (списки и метод Новый чат), SDK возвращает ответ целиком: data и meta.
  • Значение null: необязательное поле, которое не задано, в запрос не попадает. Чтобы отправить null там, где API его принимает (например, null в webhook.kind удаляет входящий вебхук бота), назовите поле в null_fields модели запроса так, как оно называется в Python: BotUpdateRequestWebhook(null_fields=["kind"]).
from pachca.models import ChatMemberRole, ReactionRequest

# Тело из одного поля → аргумент
await client.members.update_member_role(chat_id, user_id, ChatMemberRole.ADMIN)
await client.messages.pin_message(message_id)

# Тело из нескольких полей → объект-запрос
await client.reactions.add_reaction(message_id, ReactionRequest(code="👍"))

# Ответ: API возвращает {"data": Message}, SDK возвращает Message
message = await client.messages.get_message(message_id)  # Message, не {"data": Message}

Пагинация

Для методов с курсорной пагинацией SDK генерирует *_all-методы, которые автоматически обходят все страницы:

from pachca.models import Chat, ListChatsParams

# Вручную
chats: list[Chat] = []
cursor = None
while True:
    response = await client.chats.list_chats(ListChatsParams(cursor=cursor))
    if not response.data:
        break
    chats.extend(response.data)
    cursor = response.meta.paginate.next_page

# Автоматически
all_chats = await client.chats.list_chats_all()

Метод *_all есть у каждого метода с пагинацией, полный список — на странице Python SDK.

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

SDK повторяет запросы сам. Паузы между попытками описаны на странице Python SDK, общие правила повторов — в разделе Повторные запросы.

Свой HTTP-клиент

Для настройки прокси, таймаутов и других параметров HTTP используйте PachcaClient.from_client() с готовым httpx.AsyncClient. Повторы такому клиенту даёт транспорт RetryTransport из pachca.utils, прокси задаётся во внутреннем транспорте:

import httpx
from pachca.client import PACHCA_API_URL, PachcaClient
from pachca.utils import RetryTransport

http = httpx.AsyncClient(
    base_url=PACHCA_API_URL,
    headers={"Authorization": f"Bearer {token}"},
    transport=RetryTransport(httpx.AsyncHTTPTransport(proxy=httpx.Proxy("http://proxy:8080"))),
)
client = PachcaClient.from_client(http)

Полный пример: ../examples/httpclient.py

Загрузка файлов

Загрузка файла идёт в три шага: параметры загрузки, отправка файла по адресу direct_url и сообщение с ключом файла. Подробнее — в разделе Загрузка файлов.

from pachca.models import (
    FileType,
    FileUploadRequest,
    MessageCreateRequest,
    MessageCreateRequestFile,
    MessageCreateRequestMessage,
)

filename = "report.pdf"
with open(filename, "rb") as f:
    data = f.read()

# 1. Получить параметры загрузки и подставить имя файла в ключ
params = await client.files.get_upload_params()
key = params.key.replace("${filename}", filename)

# 2. Загрузить файл по адресу direct_url
await client.files.upload_file(
    params.direct_url,
    FileUploadRequest(
        content_disposition=params.content_disposition,
        acl=params.acl,
        policy=params.policy,
        x_amz_credential=params.x_amz_credential,
        x_amz_algorithm=params.x_amz_algorithm,
        x_amz_date=params.x_amz_date,
        x_amz_signature=params.x_amz_signature,
        key=key,
        bucket=params.bucket,
        file=data,
    ),
)

# 3. Отправить сообщение с файлом
await client.messages.create_message(
    MessageCreateRequest(
        message=MessageCreateRequestMessage(
            entity_id=chat_id,
            content="Отчёт за неделю",
            files=[MessageCreateRequestFile(key=key, name=filename, file_type=FileType.FILE, size=len(data))],
        )
    )
)

Полный пример: ../examples/upload.py

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

from pachca.models import ApiError, OAuthError

try:
    await client.messages.get_message(999999)
except OAuthError as e:
    print(f"Ошибка авторизации: {e.error}")
except ApiError as e:
    for item in e.errors:
        print(f"Ошибка API: {item.key}: {item.message}")

Тестирование

Для unit-тестов используйте PachcaClient.stub() — создаёт клиент без HTTP-подключения.

Методы без переопределения выбрасывают NotImplementedError("Service.method is not implemented"):

from datetime import datetime, timezone
from unittest.mock import AsyncMock
from pachca.client import MessagesService, PachcaClient
from pachca.models import Message, MessageEntityType

# Мок-сервис
mock_messages = MessagesService()
mock_messages.get_message = AsyncMock(return_value=Message(
    id=1,
    entity_type=MessageEntityType.DISCUSSION,
    entity_id=123,
    chat_id=123,
    root_chat_id=123,
    content="Test message",
    user_id=1,
    created_at=datetime.now(timezone.utc),
    url="https://app.pachca.com/chats/123?message=1",
    files=[],
    important=False,
))

# Тест
client = PachcaClient.stub(messages=mock_messages)

message = await client.messages.get_message(1)
assert message.content == "Test message"

Полный пример: ../examples/stub.py

Metadata

Release files for pachca-sdk 1.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pachca-sdk 1.8.0
File Size Uploaded Provenance Actions
pachca_sdk-1.8.0.tar.gz 46.2 kB Without provenance Details for pachca_sdk-1.8.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pachca-sdk 1.8.0
File Interpreter ABI Platform Actions
pachca_sdk-1.8.0-py3-none-any.whl Python 3 none any Details for pachca_sdk-1.8.0-py3-none-any.whl

Total release size: 91.4 kB

Release files / pachca_sdk-1.8.0.tar.gz

Download URL pachca_sdk-1.8.0.tar.gz
Size 46.2 kB
Tags Source
SHA-256 checksum
How to use checksums
fffc8802fd9764156eb9531fec6677ab1c4e606f3292679c02588d7f5bb44169
BLAKE2b-256 checksum
How to use checksums
dfda8877255c3e70a00f690154e8ee9872a0399b334f652a93a9dfb99598c367
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / pachca_sdk-1.8.0-py3-none-any.whl

Download URL pachca_sdk-1.8.0-py3-none-any.whl
Size 45.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
63582ad403121cdd1a88fc0625198d89a617c65cc76c71d4d419806137186e34
BLAKE2b-256 checksum
How to use checksums
2b9a55ddef02ea16e18473341465126e8f740b189937b931275c1a51ee12479e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Security for pachca-sdk 1.8.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.8.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page