pricezaim-sdk 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pricezaim_sdk-0.1.0/CHANGELOG.md +9 -0
- pricezaim_sdk-0.1.0/LICENSE +21 -0
- pricezaim_sdk-0.1.0/MANIFEST.in +5 -0
- pricezaim_sdk-0.1.0/PKG-INFO +184 -0
- pricezaim_sdk-0.1.0/README.md +151 -0
- pricezaim_sdk-0.1.0/docs/api.md +184 -0
- pricezaim_sdk-0.1.0/pyproject.toml +70 -0
- pricezaim_sdk-0.1.0/setup.cfg +4 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/__init__.py +35 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/client.py +327 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/exceptions.py +120 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/models.py +437 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/multipart.py +47 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/page.py +96 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/py.typed +0 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/resources/__init__.py +8 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/resources/auctions.py +122 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/resources/base.py +27 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/resources/bids.py +60 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/resources/deals.py +112 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/resources/webhooks.py +75 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/retry.py +89 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/webhooks/__init__.py +6 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/webhooks/events.py +132 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk/webhooks/signature.py +78 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk.egg-info/PKG-INFO +184 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk.egg-info/SOURCES.txt +31 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk.egg-info/dependency_links.txt +1 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk.egg-info/requires.txt +8 -0
- pricezaim_sdk-0.1.0/src/pricezaim_sdk.egg-info/top_level.txt +1 -0
- pricezaim_sdk-0.1.0/tests/test_client.py +274 -0
- pricezaim_sdk-0.1.0/tests/test_models.py +81 -0
- pricezaim_sdk-0.1.0/tests/test_webhooks.py +65 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 horatiiwork-design
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pricezaim-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the pricezaim public API
|
|
5
|
+
Author-email: horatiiwork-design <horatiiwork-design@users.noreply.github.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/horatiiwork-design/pricezaim-sdk-python
|
|
8
|
+
Project-URL: Documentation, https://github.com/horatiiwork-design/pricezaim-sdk-python/blob/main/docs/api.md
|
|
9
|
+
Project-URL: Issues, https://github.com/horatiiwork-design/pricezaim-sdk-python/issues
|
|
10
|
+
Project-URL: Source, https://github.com/horatiiwork-design/pricezaim-sdk-python
|
|
11
|
+
Keywords: pricezaim,api,sdk,auctions,loans
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: httpx>=0.27
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
28
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
30
|
+
Requires-Dist: ruff>=0.9; extra == "dev"
|
|
31
|
+
Requires-Dist: twine>=5; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# pricezaim Python SDK
|
|
35
|
+
|
|
36
|
+
Python-клиент публичного API [pricezaim](https://api.pricezaim.ru/docs).
|
|
37
|
+
Синхронный, на `httpx`, с типами, DTO и проверкой подписи вебхуков.
|
|
38
|
+
|
|
39
|
+
Требуется Python 3.10+.
|
|
40
|
+
|
|
41
|
+
## Установка
|
|
42
|
+
|
|
43
|
+
После публикации в PyPI:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install pricezaim-sdk
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
До публикации:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install "pricezaim-sdk @ git+https://github.com/horatiiwork-design/pricezaim-sdk-python.git"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Для приватного GitHub-репозитория нужен токен с доступом к нему.
|
|
56
|
+
|
|
57
|
+
## Начало работы
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
import os
|
|
61
|
+
|
|
62
|
+
from pricezaim_sdk import Client
|
|
63
|
+
|
|
64
|
+
client = Client(os.environ["PRICEZAIM_API_KEY"])
|
|
65
|
+
|
|
66
|
+
page = client.auctions.list(status="active", per_page=20)
|
|
67
|
+
|
|
68
|
+
for auction in page:
|
|
69
|
+
print(auction["id"], auction["title"])
|
|
70
|
+
|
|
71
|
+
print("Всего:", page.total)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Клиент можно закрывать явно или использовать как context manager:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
with Client(os.environ["PRICEZAIM_API_KEY"]) as client:
|
|
78
|
+
auctions = client.auctions.list()
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Параметры клиента:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
Client(
|
|
85
|
+
api_key,
|
|
86
|
+
base_url="https://api.pricezaim.ru",
|
|
87
|
+
timeout=15.0,
|
|
88
|
+
http_client=None, # свой httpx.Client, если нужен прокси или тесты
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Если API развёрнут под префиксом пути, укажите его в `base_url`: SDK
|
|
93
|
+
добавляет только `/v1/...`.
|
|
94
|
+
|
|
95
|
+
## Ресурсы
|
|
96
|
+
|
|
97
|
+
| Ресурс | Что делает |
|
|
98
|
+
|---|---|
|
|
99
|
+
| `client.auctions` | список, карточка, создание, изменение, запуск, архивация, победитель, отказ, фото и файлы |
|
|
100
|
+
| `client.bids` | свои ставки, ставки аукциона, размещение ставки |
|
|
101
|
+
| `client.deals` | список, карточка, документы, реквизиты, согласование, чат |
|
|
102
|
+
| `client.webhooks` | создание, изменение, удаление, тестовая доставка, журнал и повтор доставки |
|
|
103
|
+
|
|
104
|
+
Методы с суффиксом `_dto` возвращают dataclasses:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from pricezaim_sdk import Auction
|
|
108
|
+
|
|
109
|
+
auction = client.auctions.get_dto(991)
|
|
110
|
+
|
|
111
|
+
if isinstance(auction, Auction):
|
|
112
|
+
print(auction.required_amount)
|
|
113
|
+
print(auction.client_profile.inn if auction.client_profile else None)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
DTO переживают неполный ответ: отсутствующие поля будут `None` или пустыми
|
|
117
|
+
коллекциями. Исходный словарь доступен в `to_dict()`.
|
|
118
|
+
|
|
119
|
+
## Вебхуки
|
|
120
|
+
|
|
121
|
+
Подпись считается по сырому телу. Если пересобрать JSON, подпись не сойдётся.
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
import os
|
|
125
|
+
|
|
126
|
+
from pricezaim_sdk import WebhookEvent, WebhookEventType, verify_request
|
|
127
|
+
|
|
128
|
+
raw_body = request.body # bytes, тело запроса из вашего фреймворка
|
|
129
|
+
headers = request.headers
|
|
130
|
+
|
|
131
|
+
if not verify_request(raw_body, os.environ["PRICEZAIM_WEBHOOK_SECRET"], headers):
|
|
132
|
+
raise PermissionError("Invalid webhook signature")
|
|
133
|
+
|
|
134
|
+
event = WebhookEvent.from_json(raw_body)
|
|
135
|
+
|
|
136
|
+
if event.type is WebhookEventType.AUCTION_STARTED:
|
|
137
|
+
auction_id = event.auction_id
|
|
138
|
+
# ...
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`WebhookEvent` отдаёт `event_id`, `name`, `type`, `is_known`, `auction_id` и
|
|
142
|
+
`payload`. Неизвестное событие нужно залогировать и ответить `200`, чтобы новые
|
|
143
|
+
события на платформе не ломали приёмник.
|
|
144
|
+
|
|
145
|
+
## Повторы запросов
|
|
146
|
+
|
|
147
|
+
По умолчанию выключены:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
export PRICEZAIM_SDK_RETRIES_ENABLED=1
|
|
151
|
+
export PRICEZAIM_SDK_RETRY_ATTEMPTS=3
|
|
152
|
+
export PRICEZAIM_SDK_RETRY_BASE_DELAY_MS=200
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Повторяются `429`, `500`, `502`, `503`, `504` и сетевые ошибки. `GET`, `HEAD`,
|
|
156
|
+
`PUT`, `DELETE`, `OPTIONS` повторяются всегда; `POST` и `PATCH` — только с
|
|
157
|
+
`idempotency_key`. Ответы `400`, `401`, `403`, `404`, `422` не повторяются.
|
|
158
|
+
`Retry-After` учитывается.
|
|
159
|
+
|
|
160
|
+
## Ошибки
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from pricezaim_sdk import ApiError, ValidationError
|
|
164
|
+
|
|
165
|
+
try:
|
|
166
|
+
client.auctions.get(999999)
|
|
167
|
+
except ValidationError as exc:
|
|
168
|
+
print(exc.errors)
|
|
169
|
+
except ApiError as exc:
|
|
170
|
+
print(exc.status, exc.error_code, exc.request_id, exc.retry_after)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`TransportError` выбрасывается при сетевой ошибке, таймауте или TLS.
|
|
174
|
+
|
|
175
|
+
## Разработка
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
python -m pytest
|
|
179
|
+
ruff check src tests
|
|
180
|
+
mypy src
|
|
181
|
+
python -m build
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Справочник по методам и типам — в [`docs/api.md`](docs/api.md).
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# pricezaim Python SDK
|
|
2
|
+
|
|
3
|
+
Python-клиент публичного API [pricezaim](https://api.pricezaim.ru/docs).
|
|
4
|
+
Синхронный, на `httpx`, с типами, DTO и проверкой подписи вебхуков.
|
|
5
|
+
|
|
6
|
+
Требуется Python 3.10+.
|
|
7
|
+
|
|
8
|
+
## Установка
|
|
9
|
+
|
|
10
|
+
После публикации в PyPI:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install pricezaim-sdk
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
До публикации:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pip install "pricezaim-sdk @ git+https://github.com/horatiiwork-design/pricezaim-sdk-python.git"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Для приватного GitHub-репозитория нужен токен с доступом к нему.
|
|
23
|
+
|
|
24
|
+
## Начало работы
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
import os
|
|
28
|
+
|
|
29
|
+
from pricezaim_sdk import Client
|
|
30
|
+
|
|
31
|
+
client = Client(os.environ["PRICEZAIM_API_KEY"])
|
|
32
|
+
|
|
33
|
+
page = client.auctions.list(status="active", per_page=20)
|
|
34
|
+
|
|
35
|
+
for auction in page:
|
|
36
|
+
print(auction["id"], auction["title"])
|
|
37
|
+
|
|
38
|
+
print("Всего:", page.total)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Клиент можно закрывать явно или использовать как context manager:
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
with Client(os.environ["PRICEZAIM_API_KEY"]) as client:
|
|
45
|
+
auctions = client.auctions.list()
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Параметры клиента:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
Client(
|
|
52
|
+
api_key,
|
|
53
|
+
base_url="https://api.pricezaim.ru",
|
|
54
|
+
timeout=15.0,
|
|
55
|
+
http_client=None, # свой httpx.Client, если нужен прокси или тесты
|
|
56
|
+
)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Если API развёрнут под префиксом пути, укажите его в `base_url`: SDK
|
|
60
|
+
добавляет только `/v1/...`.
|
|
61
|
+
|
|
62
|
+
## Ресурсы
|
|
63
|
+
|
|
64
|
+
| Ресурс | Что делает |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `client.auctions` | список, карточка, создание, изменение, запуск, архивация, победитель, отказ, фото и файлы |
|
|
67
|
+
| `client.bids` | свои ставки, ставки аукциона, размещение ставки |
|
|
68
|
+
| `client.deals` | список, карточка, документы, реквизиты, согласование, чат |
|
|
69
|
+
| `client.webhooks` | создание, изменение, удаление, тестовая доставка, журнал и повтор доставки |
|
|
70
|
+
|
|
71
|
+
Методы с суффиксом `_dto` возвращают dataclasses:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from pricezaim_sdk import Auction
|
|
75
|
+
|
|
76
|
+
auction = client.auctions.get_dto(991)
|
|
77
|
+
|
|
78
|
+
if isinstance(auction, Auction):
|
|
79
|
+
print(auction.required_amount)
|
|
80
|
+
print(auction.client_profile.inn if auction.client_profile else None)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
DTO переживают неполный ответ: отсутствующие поля будут `None` или пустыми
|
|
84
|
+
коллекциями. Исходный словарь доступен в `to_dict()`.
|
|
85
|
+
|
|
86
|
+
## Вебхуки
|
|
87
|
+
|
|
88
|
+
Подпись считается по сырому телу. Если пересобрать JSON, подпись не сойдётся.
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
import os
|
|
92
|
+
|
|
93
|
+
from pricezaim_sdk import WebhookEvent, WebhookEventType, verify_request
|
|
94
|
+
|
|
95
|
+
raw_body = request.body # bytes, тело запроса из вашего фреймворка
|
|
96
|
+
headers = request.headers
|
|
97
|
+
|
|
98
|
+
if not verify_request(raw_body, os.environ["PRICEZAIM_WEBHOOK_SECRET"], headers):
|
|
99
|
+
raise PermissionError("Invalid webhook signature")
|
|
100
|
+
|
|
101
|
+
event = WebhookEvent.from_json(raw_body)
|
|
102
|
+
|
|
103
|
+
if event.type is WebhookEventType.AUCTION_STARTED:
|
|
104
|
+
auction_id = event.auction_id
|
|
105
|
+
# ...
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`WebhookEvent` отдаёт `event_id`, `name`, `type`, `is_known`, `auction_id` и
|
|
109
|
+
`payload`. Неизвестное событие нужно залогировать и ответить `200`, чтобы новые
|
|
110
|
+
события на платформе не ломали приёмник.
|
|
111
|
+
|
|
112
|
+
## Повторы запросов
|
|
113
|
+
|
|
114
|
+
По умолчанию выключены:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
export PRICEZAIM_SDK_RETRIES_ENABLED=1
|
|
118
|
+
export PRICEZAIM_SDK_RETRY_ATTEMPTS=3
|
|
119
|
+
export PRICEZAIM_SDK_RETRY_BASE_DELAY_MS=200
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Повторяются `429`, `500`, `502`, `503`, `504` и сетевые ошибки. `GET`, `HEAD`,
|
|
123
|
+
`PUT`, `DELETE`, `OPTIONS` повторяются всегда; `POST` и `PATCH` — только с
|
|
124
|
+
`idempotency_key`. Ответы `400`, `401`, `403`, `404`, `422` не повторяются.
|
|
125
|
+
`Retry-After` учитывается.
|
|
126
|
+
|
|
127
|
+
## Ошибки
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from pricezaim_sdk import ApiError, ValidationError
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
client.auctions.get(999999)
|
|
134
|
+
except ValidationError as exc:
|
|
135
|
+
print(exc.errors)
|
|
136
|
+
except ApiError as exc:
|
|
137
|
+
print(exc.status, exc.error_code, exc.request_id, exc.retry_after)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`TransportError` выбрасывается при сетевой ошибке, таймауте или TLS.
|
|
141
|
+
|
|
142
|
+
## Разработка
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
python -m pytest
|
|
146
|
+
ruff check src tests
|
|
147
|
+
mypy src
|
|
148
|
+
python -m build
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Справочник по методам и типам — в [`docs/api.md`](docs/api.md).
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# Справочник методов
|
|
2
|
+
|
|
3
|
+
## Client
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
Client(api_key, *, base_url="https://api.pricezaim.ru", timeout=15.0,
|
|
7
|
+
http_client=None, headers=None)
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
| Метод | Назначение |
|
|
11
|
+
|---|---|
|
|
12
|
+
| `client.auctions` | ресурс аукционов |
|
|
13
|
+
| `client.bids` | ресурс ставок |
|
|
14
|
+
| `client.deals` | ресурс сделок |
|
|
15
|
+
| `client.webhooks` | ресурс вебхуков |
|
|
16
|
+
| `client.get(path, params=...)` | GET |
|
|
17
|
+
| `client.post(path, payload=..., idempotency_key=...)` | POST с JSON |
|
|
18
|
+
| `client.post_multipart(path, data=..., files=...)` | POST с файлами |
|
|
19
|
+
| `client.put(path, payload)` | PUT с JSON |
|
|
20
|
+
| `client.put_multipart(path, data=..., files=...)` | PUT с файлами |
|
|
21
|
+
| `client.delete(path)` | DELETE |
|
|
22
|
+
| `client.send(...)` | запрос с JSON-ответом |
|
|
23
|
+
| `client.send_raw(...)` | `httpx.Response` |
|
|
24
|
+
| `client.request(...)` | низкоуровневый запрос |
|
|
25
|
+
| `client.close()` | закрыть HTTP-клиент |
|
|
26
|
+
| `client.retry_policy` | текущая политика повторов |
|
|
27
|
+
|
|
28
|
+
## Аукционы
|
|
29
|
+
|
|
30
|
+
| Метод | Возвращает |
|
|
31
|
+
|---|---|
|
|
32
|
+
| `list(**filters)` | `Page[dict]` |
|
|
33
|
+
| `my(**filters)` | `Page[dict]` |
|
|
34
|
+
| `list_dto(**filters)` | `Page[Auction]` |
|
|
35
|
+
| `my_dto(**filters)` | `Page[Auction]` |
|
|
36
|
+
| `get(auction_id)` | `dict` |
|
|
37
|
+
| `get_dto(auction_id)` | `Auction` |
|
|
38
|
+
| `create(payload, files=...)` | `dict` |
|
|
39
|
+
| `create_dto(payload, files=...)` | `Auction` |
|
|
40
|
+
| `update(auction_id, payload, files=...)` | `dict` |
|
|
41
|
+
| `update_dto(auction_id, payload, files=...)` | `Auction` |
|
|
42
|
+
| `start(auction_id)` | `dict` |
|
|
43
|
+
| `stop(auction_id)` | `dict` |
|
|
44
|
+
| `select_winner(auction_id, bid_id)` | `dict` |
|
|
45
|
+
| `duplicate(auction_id)` | `dict` |
|
|
46
|
+
| `restore_duplicate(auction_id)` | `dict` |
|
|
47
|
+
| `refuse(auction_id, payload)` | `dict` |
|
|
48
|
+
| `restore_refusal(auction_id)` | `dict` |
|
|
49
|
+
| `photos(auction_id)` | `dict` |
|
|
50
|
+
| `download_file(auction_id, file_id)` | `bytes` |
|
|
51
|
+
|
|
52
|
+
Файл передаётся через `FileUpload`:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from pricezaim_sdk import FileUpload
|
|
56
|
+
|
|
57
|
+
client.auctions.update(
|
|
58
|
+
991,
|
|
59
|
+
{"required_amount": 600000},
|
|
60
|
+
[FileUpload("photos[]", "/tmp/photo.jpg", "photo.jpg")],
|
|
61
|
+
)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`filters` — query-параметры API: `status`, `city`, `city[]`, `date_from`,
|
|
65
|
+
`date_to`, `page`, `per_page` и другие.
|
|
66
|
+
|
|
67
|
+
## Ставки
|
|
68
|
+
|
|
69
|
+
| Метод | Возвращает |
|
|
70
|
+
|---|---|
|
|
71
|
+
| `my(**filters)` | `Page[dict]` |
|
|
72
|
+
| `my_dto(**filters)` | `Page[Bid]` |
|
|
73
|
+
| `for_auction(auction_id, **filters)` | `Page[dict]` |
|
|
74
|
+
| `for_auction_dto(auction_id, **filters)` | `Page[Bid]` |
|
|
75
|
+
| `place(auction_id, payload, idempotency_key=...)` | `dict` |
|
|
76
|
+
| `place_dto(auction_id, payload, idempotency_key=...)` | `Bid` |
|
|
77
|
+
|
|
78
|
+
`payload`: `amount`, `interest_rate`, `term`, `comment`.
|
|
79
|
+
|
|
80
|
+
## Сделки
|
|
81
|
+
|
|
82
|
+
| Метод | Возвращает |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `list(**filters)` | `Page[dict]` |
|
|
85
|
+
| `list_dto(**filters)` | `Page[Deal]` |
|
|
86
|
+
| `get(deal_id)` | `dict` |
|
|
87
|
+
| `get_dto(deal_id)` | `Deal` |
|
|
88
|
+
| `documents(deal_id)` | `dict` |
|
|
89
|
+
| `documents_dto(deal_id)` | `list[DealDocument]` |
|
|
90
|
+
| `upload_documents(deal_id, files, fields=..., idempotency_key=...)` | `dict` |
|
|
91
|
+
| `requisites(deal_id)` | `dict` |
|
|
92
|
+
| `approve(deal_id, payload=..., idempotency_key=...)` | `dict` |
|
|
93
|
+
| `chat(deal_id, **filters)` | `dict` |
|
|
94
|
+
| `send_chat(deal_id, message, payload=..., idempotency_key=...)` | `dict` |
|
|
95
|
+
| `download_document(deal_id, document_id)` | `bytes` |
|
|
96
|
+
| `delete_document(deal_id, document_id)` | `dict` |
|
|
97
|
+
|
|
98
|
+
## Вебхуки
|
|
99
|
+
|
|
100
|
+
| Метод | Возвращает |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `list()` | `dict` |
|
|
103
|
+
| `list_dto()` | `list[Webhook]` |
|
|
104
|
+
| `create(payload, idempotency_key=...)` | `dict` |
|
|
105
|
+
| `create_dto(payload, idempotency_key=...)` | `Webhook` |
|
|
106
|
+
| `update(webhook_id, payload)` | `dict` |
|
|
107
|
+
| `update_dto(webhook_id, payload)` | `Webhook` |
|
|
108
|
+
| `delete(webhook_id)` | `dict` |
|
|
109
|
+
| `test(webhook_id)` | `dict` |
|
|
110
|
+
| `deliveries(webhook_id, **filters)` | `Page[dict]` |
|
|
111
|
+
| `retry_delivery(webhook_id, delivery_id)` | `dict` |
|
|
112
|
+
|
|
113
|
+
## Page
|
|
114
|
+
|
|
115
|
+
`Page` поддерживает `len()`, `iter()`, индексацию и `map()`.
|
|
116
|
+
|
|
117
|
+
| Свойство / метод | Возвращает |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `items` / `data` | `list` |
|
|
120
|
+
| `meta` | `dict` |
|
|
121
|
+
| `raw` | `dict` |
|
|
122
|
+
| `total` | `int` |
|
|
123
|
+
| `current_page` | `int` |
|
|
124
|
+
| `last_page` | `int` |
|
|
125
|
+
| `per_page` | `int` |
|
|
126
|
+
| `is_empty()` | `bool` |
|
|
127
|
+
| `map(fn)` | `Page` |
|
|
128
|
+
|
|
129
|
+
## DTO
|
|
130
|
+
|
|
131
|
+
Все DTO имеют `from_dict()` и `to_dict()`. `to_dict()` возвращает исходный
|
|
132
|
+
ответ API.
|
|
133
|
+
|
|
134
|
+
| DTO | Поля |
|
|
135
|
+
|---|---|
|
|
136
|
+
| `Auction` | `id`, `uuid`, `status`, `required_amount`, `can_bid`, `client_profile` |
|
|
137
|
+
| `ClientProfile` | `inn`, `passport_number`, `income_salary`; содержит ПДн |
|
|
138
|
+
| `Bid` | `id`, `auction_id`, `amount`, `interest_rate`, `term` |
|
|
139
|
+
| `Deal` | `id`, `auction_id`, `status`, `documents`, `document_objects()` |
|
|
140
|
+
| `DealDocument` | `id`, `original_name`, `mime`, `size` |
|
|
141
|
+
| `Webhook` | `id`, `url`, `events`, `active`, `has_secret` |
|
|
142
|
+
|
|
143
|
+
## Вебхуки: подпись и событие
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
sign(payload, secret) -> str
|
|
147
|
+
verify(payload, secret, signature, timestamp=None, tolerance=300) -> bool
|
|
148
|
+
verify_request(payload, secret, headers, tolerance=300) -> bool
|
|
149
|
+
|
|
150
|
+
WebhookEvent.from_json(raw)
|
|
151
|
+
WebhookEvent.from_dict(payload)
|
|
152
|
+
|
|
153
|
+
event.event_id
|
|
154
|
+
event.name
|
|
155
|
+
event.type
|
|
156
|
+
event.is_known
|
|
157
|
+
event.auction_id
|
|
158
|
+
event.payload
|
|
159
|
+
event.to_dict()
|
|
160
|
+
event.is_(event_type)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Повторы
|
|
164
|
+
|
|
165
|
+
| Ситуация | Повтор |
|
|
166
|
+
|---|---|
|
|
167
|
+
| `429`, `500`, `502`, `503`, `504` | да |
|
|
168
|
+
| сеть или таймаут | да |
|
|
169
|
+
| `GET`, `HEAD`, `PUT`, `DELETE`, `OPTIONS` | да |
|
|
170
|
+
| `POST`, `PATCH` без `idempotency_key` | нет |
|
|
171
|
+
| `POST`, `PATCH` с `idempotency_key` | да |
|
|
172
|
+
| `400`, `401`, `403`, `404`, `422` | нет |
|
|
173
|
+
|
|
174
|
+
Включаются переменной `PRICEZAIM_SDK_RETRIES_ENABLED`. Дополнительно:
|
|
175
|
+
`PRICEZAIM_SDK_RETRY_ATTEMPTS`, `PRICEZAIM_SDK_RETRY_BASE_DELAY_MS`.
|
|
176
|
+
|
|
177
|
+
## Исключения
|
|
178
|
+
|
|
179
|
+
`ApiError` — HTTP-ошибка или не-JSON ответ. Доступны `status`, `error_code`,
|
|
180
|
+
`body`, `headers`, `request_id`, `retry_after`, `is_rate_limited`.
|
|
181
|
+
|
|
182
|
+
`ValidationError` — ответ `422`, ошибки полей в `errors`.
|
|
183
|
+
|
|
184
|
+
`TransportError` — сеть, DNS, таймаут, TLS.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "pricezaim-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python client for the pricezaim public API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{name = "horatiiwork-design", email = "horatiiwork-design@users.noreply.github.com"},
|
|
15
|
+
]
|
|
16
|
+
keywords = ["pricezaim", "api", "sdk", "auctions", "loans"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Programming Language :: Python :: 3.13",
|
|
25
|
+
"Programming Language :: Python :: 3.14",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
"Typing :: Typed",
|
|
28
|
+
]
|
|
29
|
+
dependencies = ["httpx>=0.27"]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"build>=1.2",
|
|
34
|
+
"mypy>=1.10",
|
|
35
|
+
"pytest>=8",
|
|
36
|
+
"ruff>=0.9",
|
|
37
|
+
"twine>=5",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://github.com/horatiiwork-design/pricezaim-sdk-python"
|
|
42
|
+
Documentation = "https://github.com/horatiiwork-design/pricezaim-sdk-python/blob/main/docs/api.md"
|
|
43
|
+
Issues = "https://github.com/horatiiwork-design/pricezaim-sdk-python/issues"
|
|
44
|
+
Source = "https://github.com/horatiiwork-design/pricezaim-sdk-python"
|
|
45
|
+
|
|
46
|
+
[tool.setuptools.packages.find]
|
|
47
|
+
where = ["src"]
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.package-data]
|
|
50
|
+
pricezaim_sdk = ["py.typed"]
|
|
51
|
+
|
|
52
|
+
[tool.ruff]
|
|
53
|
+
target-version = "py310"
|
|
54
|
+
line-length = 100
|
|
55
|
+
|
|
56
|
+
[tool.ruff.lint]
|
|
57
|
+
select = ["E", "F", "I", "UP", "B", "SIM", "RUF"]
|
|
58
|
+
ignore = ["PYI034", "RUF001", "RUF002", "RUF003"]
|
|
59
|
+
|
|
60
|
+
[tool.mypy]
|
|
61
|
+
python_version = "3.10"
|
|
62
|
+
check_untyped_defs = true
|
|
63
|
+
no_implicit_optional = true
|
|
64
|
+
warn_redundant_casts = true
|
|
65
|
+
warn_unused_ignores = true
|
|
66
|
+
ignore_missing_imports = true
|
|
67
|
+
|
|
68
|
+
[tool.pytest.ini_options]
|
|
69
|
+
pythonpath = ["src"]
|
|
70
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""Python SDK для публичного API pricezaim."""
|
|
2
|
+
|
|
3
|
+
from .client import VERSION, Client
|
|
4
|
+
from .exceptions import ApiError, PricezaimError, TransportError, ValidationError
|
|
5
|
+
from .models import Auction, Bid, ClientProfile, Deal, DealDocument, Webhook
|
|
6
|
+
from .multipart import FileUpload
|
|
7
|
+
from .page import Page
|
|
8
|
+
from .retry import RetryPolicy
|
|
9
|
+
from .webhooks import WebhookEvent, WebhookEventType, sign, verify, verify_request
|
|
10
|
+
|
|
11
|
+
__version__ = VERSION
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"VERSION",
|
|
15
|
+
"ApiError",
|
|
16
|
+
"Auction",
|
|
17
|
+
"Bid",
|
|
18
|
+
"Client",
|
|
19
|
+
"ClientProfile",
|
|
20
|
+
"Deal",
|
|
21
|
+
"DealDocument",
|
|
22
|
+
"FileUpload",
|
|
23
|
+
"Page",
|
|
24
|
+
"PricezaimError",
|
|
25
|
+
"RetryPolicy",
|
|
26
|
+
"TransportError",
|
|
27
|
+
"ValidationError",
|
|
28
|
+
"Webhook",
|
|
29
|
+
"WebhookEvent",
|
|
30
|
+
"WebhookEventType",
|
|
31
|
+
"__version__",
|
|
32
|
+
"sign",
|
|
33
|
+
"verify",
|
|
34
|
+
"verify_request",
|
|
35
|
+
]
|