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.9.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.9.0
File Size Uploaded Provenance Actions
pachca_sdk-1.9.0.tar.gz 46.4 kB Without provenance Details for pachca_sdk-1.9.0.tar.gz

Built distribution (wheel)

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

Total release size: 91.6 kB

Release files / pachca_sdk-1.9.0.tar.gz

Download URL pachca_sdk-1.9.0.tar.gz
Size 46.4 kB
Tags Source
SHA-256 checksum
How to use checksums
e1c9f2509b2f523de2643441449829bf697a0b995ef61eec537b048910ce6b2c
BLAKE2b-256 checksum
How to use checksums
a215bb5f6540975a87ccfcfbae20428536029acf5f9eb46b70d8b0fcb8d42331
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.9.0-py3-none-any.whl

Download URL pachca_sdk-1.9.0-py3-none-any.whl
Size 45.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
606a0de106a25be32d05d27366e5700a7550c7ecb5f418d851fed7d54d2ab74e
BLAKE2b-256 checksum
How to use checksums
823722d0a44c2c1744be28b5e9f92b7259cc7fa5fc188e650d34946555b6f5a9
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.9.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.9.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