Отчёт покрытия Avito API: покрытие API.
Получение ключей — 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_.
CLI использует тот же публичный SDK и удобен для smoke-проверок, скриптов и операционных задач:
avito account add main --client-id client-id --user-id 123 avito --profile main account get-self avito --json --no-input --profile main account get-balance --user-id 123
account add спросит Client Secret скрытым prompt. Для CI используйте
--client-secret-stdin, чтобы не передавать секрет в аргументах shell.
Подробно: CLI how-to
и CLI reference.
avito-py — Python SDK для работы с Avito API через единые sync/async фасады
AvitoClient и AsyncAvitoClient.
poetry add avito-py
или
pip install avito-py
Требование к интерпретатору: Python 3.12, 3.13 или 3.14.
SDK предоставляет три нормативных способа создания клиента — от самого простого к самому явному.
from avito import AvitoClient with AvitoClient.from_env() as avito: ...
Короткий путь без промежуточных объектов:
from avito import AvitoClient with AvitoClient(client_id="client-id", client_secret="client-secret") as avito: ...
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 не меняются у живого клиента — вместо этого создаётся новый клиент.
Async-поверхность использует те же доменные методы и модели, но требует async with:
from avito import AsyncAvitoClient async with AsyncAvitoClient.from_env() as avito: profile = await avito.account().get_self() listings = await (await avito.ad(user_id=123).list(limit=20)).materialize()
Подробный контракт async lifecycle, ASGI-рецепты и ограничения описаны в async how-to.
| Переменная | Обязательная | Описание |
|---|---|---|
AVITO_CLIENT_ID |
да | Client ID OAuth-приложения |
AVITO_CLIENT_SECRET |
да | Client Secret OAuth-приложения |
AVITO_BASE_URL |
нет | Базовый URL API (по умолчанию https://api.avito.ru) |
AVITO_USER_ID |
нет | ID пользователя по умолчанию |
AVITO_USER_AGENT_SUFFIX |
нет | Суффикс к заголовку User-Agent |
AVITO_SCOPE |
нет | OAuth scope |
AVITO_REFRESH_TOKEN |
нет | Refresh token для предварительного обмена |
AVITO_AUTOTEKA_CLIENT_ID |
нет | Client ID для Автотека API |
AVITO_AUTOTEKA_CLIENT_SECRET |
нет | Client Secret для Автотека API |
AVITO_AUTOTEKA_SCOPE |
нет | OAuth scope для Автотека API |
Полный список переменных, включая URL-overrides, таймауты и retry-политику, — в справочнике по конфигурации.
Правила resolution:
- значения из process environment имеют приоритет над
.env; AvitoSettings.from_env()иAvitoClient.from_env()детерминированно читают.envиз текущей рабочей директории или из переданногоenv_file;- при отсутствии
AVITO_CLIENT_IDилиAVITO_CLIENT_SECRETSDK поднимаетConfigurationErrorпри создании клиента, до первого HTTP-запроса.
Для async-кода используйте AsyncAvitoClient. Он повторяет доменную поверхность
AvitoClient: фабрики (account(), ad(), chat(), order() и другие),
аргументы методов и возвращаемые SDK-модели остаются теми же, но сетевые вызовы
выполняются через await.
AsyncAvitoClient обязательно открывается через async with: в этот момент SDK
создаёт loop-bound httpx.AsyncClient, async locks и transport. Для ручного
закрытия есть await avito.aclose(), но для application-кода предпочтителен
контекстный менеджер.
from avito import AsyncAvitoClient async def load_active_ads() -> list[str]: async with AsyncAvitoClient.from_env() as avito: profile = await avito.account().get_self() ads = await avito.ad(user_id=profile.id).list(status="active", limit=20) items = await ads.materialize() return [item.title for item in items]
Async-пагинация возвращает AsyncPaginatedList[T], а не обычный list.
Читайте страницы через async for или явно материализуйте результат:
from avito import AsyncAvitoClient async def print_ads() -> None: async with AsyncAvitoClient.from_env() as avito: ads = await avito.ad(user_id=123).list(status="active", limit=100) async for item in ads: print(item.title)
Для ASGI-приложений создавайте один AsyncAvitoClient в lifespan приложения и
закрывайте его на shutdown. Один экземпляр клиента нельзя переносить между event
loop.
from collections.abc import AsyncIterator from contextlib import asynccontextmanager from fastapi import FastAPI from avito import AsyncAvitoClient @asynccontextmanager async def lifespan(app: FastAPI) -> AsyncIterator[None]: async with AsyncAvitoClient.from_env() as avito: app.state.avito = avito yield app = FastAPI(lifespan=lifespan)
Подробнее: Асинхронный режим и справочник AvitoClient и AsyncAvitoClient.
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_item_stats( date_from="2026-04-01", date_to="2026-04-23", )
user_id можно передать явно, задать через AVITO_USER_ID или оставить пустым для read-only вызовов, где SDK может определить пользователя через account().get_self(). Если идентификатор не удалось определить, SDK поднимает ValidationError с подсказкой, как вызвать метод правильно. Для OAuth secret используйте AVITO_CLIENT_SECRET.
Статистические методы принимают date, datetime и ISO-строки, а в Avito API отправляют дату в формате YYYY-MM-DD. Модель Listing нормализует основные поля объявления: title, price, status, description, url, category, city, published_at, updated_at, is_moderated, is_visible.
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=datetime(2026, 4, 20), finish_time=datetime(2026, 4, 27), 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 with AvitoClient.from_env() as avito: orders = avito.order().list() label_task = avito.order_label().create(order_ids=["100500"]) label_pdf = avito.order_label(task_id=label_task.task_id).download() stock_info = avito.stock().get(item_ids=[100500])
from avito import AvitoClient with AvitoClient.from_env() as avito: vacancies = avito.vacancy().list(query="python") application_ids = avito.application().get_ids(updated_at_from="2026-04-18") applications = avito.application().get_by_ids(ids=[application_ids.items[0].id]) resumes = avito.resume().list(query="оператор") webhooks = avito.job_webhook().list()
from avito import AvitoClient with AvitoClient.from_env() as avito: calls = avito.cpa_call().list( date_time_from="2026-04-18T00:00:00Z", limit=100, ) calltracking = avito.call_tracking_call(10).get() records = avito.call_tracking_call(10).download()
from avito import AvitoClient with AvitoClient.from_env() as avito: catalog = avito.autoteka_vehicle().resolve_catalog(brand_id=1) preview = avito.autoteka_vehicle().create_preview_by_vin(vin="XTA00000000000000") report = avito.autoteka_report().create_report(preview_id=int(preview.preview_id or 0)) reports = avito.autoteka_report().list_reports()
from avito import AvitoClient from avito.realty import RealtyPricePeriod with AvitoClient.from_env() as avito: booking = avito.realty_booking(20, user_id=10) booking.update_bookings_info(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( periods=[RealtyPricePeriod(date_from="2026-05-01", price=5000)] ) reviews = avito.review().list() tariff = avito.tariff().get_tariff_info()
review().list() по умолчанию запрашивает первую страницу отзывов (page=1, limit=50). Для явной пагинации передайте page, offset или limit напрямую.
Публичные list-операции, которые поддерживают lazy pagination, возвращают обычные SDK-результаты, а поле items в них типизировано как PaginatedList[T] и ведёт себя как list-like коллекция.
Стабильный публичный контракт:
- первая страница загружается сразу, остальные подгружаются только при чтении элементов за её пределами;
- доступ к уже загруженным элементам не делает повторных запросов;
- частичная итерация и slicing загружают только необходимые страницы;
- пустая коллекция не приводит к дополнительным запросам;
- ошибка на последующей странице поднимается в момент её чтения;
- явная полная материализация выполняется через
items.materialize()и загружает всё ровно один раз.
Пример:
from avito import AvitoClient with AvitoClient.from_env() as avito: items = avito.ad(user_id=123).list(status="active", limit=50, page_size=25) first = items[0] preview = items[:10] all_items = items.materialize()
В ad().list() параметр limit ограничивает общий максимум элементов результата, а page_size задаёт размер страницы upstream API.
Все исключения SDK наследуются от AvitoError и импортируются из avito.core.exceptions. HTTP-коды отображаются в конкретные типы:
400,422→ValidationError401→AuthenticationError403→AuthorizationError409→ConflictError429→RateLimitError- прочие
5xxи нераспознанные ответы →UpstreamApiError - транспортные сбои →
TransportError - ошибки маппинга ответа →
ResponseMappingError
AuthenticationError (401) и AuthorizationError (403) — семантически разные ошибки и не состоят в отношении наследования. Тексты сообщений написаны на русском языке. Секреты (access token, client_secret, Authorization) автоматически санитайзятся из сообщений и metadata.
Для диагностики доступны структурированные поля operation, status / status_code, error_code, message, details, retry_after, request_id, metadata, payload и headers. Например, у RateLimitError можно прочитать retry_after, а у ошибок валидации — details, если upstream вернул подробности по параметрам.
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 quality
make buildДля репозитория настроены два workflow:
CIзапускается на каждыйpushвmain/masterи на каждыйpull_request, выполняетmake quality, docs-gates и один полный pytest-прогон через coverage.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/site/reference — справочник публичного API SDK