avito-py — Python SDK для работы с Avito API через единый объектный фасад AvitoClient.
Цели SDK:
- скрыть transport, OAuth и retry-логику от пользовательского кода;
- возвращать типизированные
dataclass-модели вместо сырого JSON; - дать единый вход в доменные сценарии вида
avito.ad(...).get()иavito.chat(...).send_message(...); - покрыть все swagger-документы из каталога docs.
Каталог 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() as avito:
profile = avito.account().get_self()
ad = avito.ad(42).get()
print(profile.name)
print(ad.title)По умолчанию настройки читаются из переменных окружения с префиксом AVITO_.
Официальный способ конфигурации SDK:
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",
),
)
client = AvitoClient(settings)Инициализация из окружения и .env:
from avito import AvitoClient, AvitoSettings
settings = AvitoSettings.from_env()
client = AvitoClient.from_env()Поддерживаемые env-переменные и alias-имена:
AVITO_BASE_URLAVITO_USER_IDAVITO_AUTH__CLIENT_ID, alias:AVITO_CLIENT_IDAVITO_AUTH__CLIENT_SECRET, alias:AVITO_CLIENT_SECRETAVITO_AUTH__REFRESH_TOKEN, alias:AVITO_REFRESH_TOKENAVITO_AUTH__SCOPE, alias:AVITO_SCOPEAVITO_AUTH__TOKEN_URL, alias:AVITO_TOKEN_URLAVITO_AUTH__ALTERNATE_TOKEN_URL, alias:AVITO_ALTERNATE_TOKEN_URLAVITO_AUTH__AUTOTEKA_TOKEN_URL, alias:AVITO_AUTOTEKA_TOKEN_URLAVITO_AUTH__AUTOTEKA_CLIENT_ID, alias:AVITO_AUTOTEKA_CLIENT_IDAVITO_AUTH__AUTOTEKA_CLIENT_SECRET, alias:AVITO_AUTOTEKA_CLIENT_SECRETAVITO_AUTH__AUTOTEKA_SCOPE, alias:AVITO_AUTOTEKA_SCOPE
Правила resolution:
- значения из process environment имеют приоритет над
.env; AvitoSettings.from_env()иAvitoClient.from_env()детерминированно читают.envиз текущей рабочей директории или из переданногоenv_file;- при отсутствии
client_idилиclient_secretSDK завершает инициализацию с typed-ошибкойConfigurationError.
from avito import AvitoClient
with AvitoClient() 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() 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() 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() 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)from avito import AvitoClient
from avito.orders import OrderLabelsRequest, StockInfoRequest
with AvitoClient() 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() 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()from avito import AvitoClient
from avito.cpa import CpaCallsByTimeRequest
with AvitoClient() 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()Публичные list-операции, которые поддерживают lazy pagination, возвращают обычные SDK-результаты, а поле items в них ведет себя как list-like коллекция PaginatedList.
Текущий стабильный контракт:
- первая страница загружается сразу, остальные страницы подгружаются только при чтении элементов за ее пределами;
- доступ к уже загруженным элементам не делает повторных запросов;
- частичная итерация и slicing загружают только необходимые страницы;
- явная полная материализация выполняется через
items.materialize().
Пример:
from avito import AvitoClient
with AvitoClient() 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()from avito import AvitoClient
from avito.autoteka import CatalogResolveRequest, PreviewReportRequest, VinRequest
with AvitoClient() 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() 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()SDK не раскрывает сырой transport в основном API, но даёт безопасный debug snapshot без секретов:
from avito import AvitoClient
client = AvitoClient()
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Для репозитория настроены два 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