Skip to content

p141592/avito_python_api

Repository files navigation

SDK для Avito

CI Coverage Status PyPI Downloads API coverage

avito-py — синхронный Python SDK для работы с Avito API через единый объектный фасад AvitoClient.

Цели SDK:

  • скрыть transport, OAuth и retry-логику от пользовательского кода;
  • возвращать типизированные dataclass-модели вместо сырого JSON;
  • дать единый вход в доменные сценарии вида avito.ad(...).get() и avito.chat(...).send_message(...);
  • покрыть все swagger-документы из каталога docs.

SDK является синхронным. Любая асинхронная поддержка, если она появится, будет жить в отдельном namespace avito.aio и никогда не будет смешана с sync-классами в одном модуле.

Каталог docs рассматривается как upstream API contract. Эти файлы не редактируются вручную при развитии SDK: публичные модели, мапперы и тесты должны подстраиваться под documented shape из docs/*.

Установка

poetry add avito-py

или

pip install avito-py

Требование к интерпретатору: Python 3.14 и выше в рамках ветки 3.x. Репозиторий и релизный контур валидируются именно на Python 3.14.

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

Получение ключей — https://www.avito.ru/professionals/api

from avito import AvitoClient

with AvitoClient.from_env() as avito:
    profile = avito.account().get_self()
    ad = avito.ad(item_id=42, user_id=123).get()

print(profile.name)
print(ad.title)

По умолчанию настройки читаются из переменных окружения с префиксом AVITO_.

Инициализация клиента

SDK предоставляет три нормативных способа создания клиента — от самого простого к самому явному.

1. Из переменных окружения

from avito import AvitoClient

with AvitoClient.from_env() as avito:
    ...

2. Напрямую через client_id / client_secret

Короткий путь без промежуточных объектов:

from avito import AvitoClient

with AvitoClient(client_id="client-id", client_secret="client-secret") as avito:
    ...

3. Полная конфигурация через AvitoSettings

from avito import AuthSettings, AvitoClient, AvitoSettings

settings = AvitoSettings(
    base_url="https://api.avito.ru",
    user_id=123,
    auth=AuthSettings(
        client_id="client-id",
        client_secret="client-secret",
    ),
)

with AvitoClient(settings) as avito:
    ...

Все опциональные параметры конструктора — keyword-only. AvitoClient иммутабелен: base_url, таймауты, retry-политика и auth не меняются у живого клиента — вместо этого создаётся новый клиент.

Переменные окружения

Поддерживаемые env-переменные и alias-имена:

  • AVITO_BASE_URL
  • AVITO_USER_ID
  • AVITO_AUTH__CLIENT_ID, alias: AVITO_CLIENT_ID
  • AVITO_AUTH__CLIENT_SECRET, alias: AVITO_CLIENT_SECRET
  • AVITO_AUTH__REFRESH_TOKEN, alias: AVITO_REFRESH_TOKEN
  • AVITO_AUTH__SCOPE, alias: AVITO_SCOPE
  • AVITO_AUTH__TOKEN_URL, alias: AVITO_TOKEN_URL
  • AVITO_AUTH__ALTERNATE_TOKEN_URL, alias: AVITO_ALTERNATE_TOKEN_URL
  • AVITO_AUTH__AUTOTEKA_TOKEN_URL, alias: AVITO_AUTOTEKA_TOKEN_URL
  • AVITO_AUTH__AUTOTEKA_CLIENT_ID, alias: AVITO_AUTOTEKA_CLIENT_ID
  • AVITO_AUTH__AUTOTEKA_CLIENT_SECRET, alias: AVITO_AUTOTEKA_CLIENT_SECRET
  • AVITO_AUTH__AUTOTEKA_SCOPE, alias: AVITO_AUTOTEKA_SCOPE

Правила resolution:

  • значения из process environment имеют приоритет над .env;
  • AvitoSettings.from_env() и AvitoClient.from_env() детерминированно читают .env из текущей рабочей директории или из переданного env_file;
  • при отсутствии client_id или client_secret SDK завершает инициализацию с typed-ошибкой ConfigurationError до первого HTTP-запроса.

Примеры по доменам

Аккаунт и объявления

from avito import AvitoClient

with AvitoClient.from_env() as avito:
    account = avito.account(user_id=123)
    balance = account.get_balance()
    ad = avito.ad(item_id=42, user_id=123).get()
    stats = avito.ad_stats(item_id=42, user_id=123).get()

Автозагрузка

from avito import AvitoClient

with AvitoClient.from_env() as avito:
    profile = avito.autoload_profile(user_id=123).get()
    report = avito.autoload_report(report_id=777).get()

Мессенджер

from avito import AvitoClient
from avito.messenger import UploadImageFile

with AvitoClient.from_env() as avito:
    chats = avito.chat(user_id=123).list()
    message = avito.chat_message(chat_id="chat-1", user_id=123).send_message(
        message="Здравствуйте"
    )
    uploaded = avito.chat_media(user_id=123).upload_images(
        files=[
            UploadImageFile(
                field_name="image",
                filename="photo.jpg",
                content=b"...",
                content_type="image/jpeg",
            )
        ]
    )
    subscriptions = avito.chat_webhook().list()

Продвижение

from avito import AvitoClient
from datetime import datetime

with AvitoClient.from_env() as avito:
    services = avito.promotion_order().list_orders()
    forecast = avito.bbip_promotion(item_id=42).get_forecasts(items=[])
    budget = avito.autostrategy_campaign().create_budget(
        campaign_type="AS",
        start_time="2026-04-20T00:00:00Z",
        finish_time="2026-04-27T00:00:00Z",
        items=[42, 43],
    )
    campaign = avito.autostrategy_campaign(campaign_id=15).get()
    campaigns = avito.autostrategy_campaign().list(
        limit=50,
        status_id=[1, 2],
        order_by=[("startTime", "asc")],
        updated_from=datetime(2026, 4, 1),
        updated_to=datetime(2026, 4, 30),
    )

print(budget.calc_id)
print(campaign.campaign.title if campaign.campaign else None)
print(campaigns.total_count)

Write-операции продвижения, поддерживающие сухой прогон, принимают dry_run: bool = False. При dry_run=True SDK валидирует параметры, строит тот же payload, что и в реальном вызове, но не выполняет сетевой запрос и возвращает PromotionActionResult со статусом preview/validated.

Заказы и доставка

from avito import AvitoClient
from avito.orders import OrderLabelsRequest, StockInfoRequest

with AvitoClient.from_env() as avito:
    orders = avito.order().list()
    label_task = avito.order_label().create(request=OrderLabelsRequest(order_ids=["100500"]))
    label_pdf = avito.order_label(task_id=label_task.task_id).download()
    stock_info = avito.stock().get(request=StockInfoRequest(item_ids=[100500]))

Работа

from avito import AvitoClient
from avito.jobs import ApplicationIdsQuery, ResumeSearchQuery

with AvitoClient.from_env() as avito:
    vacancies = avito.vacancy().list()
    applications = avito.application().list(
        query=ApplicationIdsQuery(updated_at_from="2026-04-18")
    )
    resumes = avito.resume().list(query=ResumeSearchQuery(query="оператор"))
    webhooks = avito.job_webhook().list()

CPA и CallTracking

from avito import AvitoClient
from avito.cpa import CpaCallsByTimeRequest

with AvitoClient.from_env() as avito:
    calls = avito.cpa_call().list(
        request=CpaCallsByTimeRequest(
            date_time_from="2026-04-18T00:00:00Z",
            date_time_to="2026-04-19T00:00:00Z",
        )
    )
    calltracking = avito.call_tracking_call(10).get()
    records = avito.call_tracking_call(10).download()

Автотека

from avito import AvitoClient
from avito.autoteka import CatalogResolveRequest, PreviewReportRequest, VinRequest

with AvitoClient.from_env() as avito:
    catalog = avito.autoteka_vehicle().resolve_catalog(
        request=CatalogResolveRequest(brand_id=1)
    )
    preview = avito.autoteka_vehicle().create_preview_by_vin(
        request=VinRequest(vin="XTA00000000000000")
    )
    report = avito.autoteka_report().create_report(
        request=PreviewReportRequest(preview_id=int(preview.preview_id or 0))
    )
    reports = avito.autoteka_report().list_reports()

Недвижимость, отзывы и тарифы

from avito import AvitoClient
from avito.realty import RealtyBookingsUpdateRequest, RealtyPricePeriod, RealtyPricesUpdateRequest

with AvitoClient.from_env() as avito:
    booking = avito.realty_booking(20, user_id=10)
    booking.update_bookings_info(
        request=RealtyBookingsUpdateRequest(blocked_dates=["2026-05-01"])
    )
    bookings = booking.list_realty_bookings(date_start="2026-05-01", date_end="2026-05-05")
    avito.realty_pricing(20, user_id=10).update_realty_prices(
        request=RealtyPricesUpdateRequest(
            periods=[RealtyPricePeriod(date_from="2026-05-01", price=5000)]
        )
    )
    reviews = avito.review().list()
    tariff = avito.tariff().get_tariff_info()

Пагинация

Публичные list-операции, которые поддерживают lazy pagination, возвращают обычные SDK-результаты, а поле items в них типизировано как PaginatedList[T] и ведёт себя как list-like коллекция.

Стабильный публичный контракт:

  • первая страница загружается сразу, остальные подгружаются только при чтении элементов за её пределами;
  • доступ к уже загруженным элементам не делает повторных запросов;
  • частичная итерация и slicing загружают только необходимые страницы;
  • пустая коллекция не приводит к дополнительным запросам;
  • ошибка на последующей странице поднимается в момент её чтения;
  • явная полная материализация выполняется через items.materialize() и загружает всё ровно один раз.

Пример:

from avito import AvitoClient

with AvitoClient.from_env() as avito:
    result = avito.ad(user_id=123).list(status="active", limit=50)

    first = result.items[0]
    preview = result.items[:10]
    all_items = result.items.materialize()

Ошибки

Все исключения SDK наследуются от AvitoError и импортируются из avito.core.exceptions. HTTP-коды отображаются в конкретные типы:

  • 400, 422ValidationError
  • 401AuthenticationError
  • 403AuthorizationError
  • 409ConflictError
  • 429RateLimitError
  • прочие 5xx и нераспознанные ответы → UpstreamApiError
  • транспортные сбои → TransportError
  • ошибки маппинга ответа → ResponseMappingError

AuthenticationError (401) и AuthorizationError (403) — семантически разные ошибки и не состоят в отношении наследования. Тексты сообщений написаны на русском языке. Секреты (access token, client_secret, Authorization) автоматически санитайзятся из сообщений и metadata.

Отладка интеграции

SDK не раскрывает сырой transport в основном API, но даёт безопасный debug snapshot без секретов:

from avito import AvitoClient

client = AvitoClient.from_env()
info = client.debug_info()

print(info.base_url)
print(info.user_id)
print(info.retry_max_attempts)
client.close()

debug_info() подходит для smoke-проверок окружения и диагностики конфигурации. Стабильный контракт включает base_url, user_id, флаг requires_auth, таймауты и retry-настройки. Access token, client_secret и Authorization header в этот снимок не попадают.

Проверки качества

Минимальный релизный набор:

make check

Для локальной разработки команды разделены:

make fmt
make lint
make typecheck
make test
make build

GitHub Actions

Для репозитория настроены два workflow:

  • CI запускается на каждый push в main/master и на каждый pull_request, выполняет make check.
  • Release запускается при пуше тега вида v*, выставляет версию пакета из тега, повторно выполняет make check, публикует пакет на PyPI и создаёт GitHub Release.

Для публикации релиза нужно добавить secret:

  • PYPI_API_TOKEN — токен публикации в PyPI для poetry publish.

Порядок релиза:

git tag v1.0.2
git push origin v1.0.2

Документация репозитория

  • STYLEGUIDE.md — нормативные архитектурные правила
  • docs/inventory.md — матрица соответствия swagger-операций и публичного API SDK

About

Avito SDK для python

Topics

Resources

License

Stars

Watchers

Forks

Contributors