async-amazon-ads-api-v1 0.3.0__py3-none-any.whl
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.
- async_amazon_ads_api_v1/__init__.py +30 -0
- async_amazon_ads_api_v1/_base.py +171 -0
- async_amazon_ads_api_v1/client/sb/__init__.py +121 -0
- async_amazon_ads_api_v1/client/sb/ad_extensions.py +39 -0
- async_amazon_ads_api_v1/client/sb/ad_groups.py +41 -0
- async_amazon_ads_api_v1/client/sb/ads.py +37 -0
- async_amazon_ads_api_v1/client/sb/advertising_deal_targets.py +41 -0
- async_amazon_ads_api_v1/client/sb/advertising_deals.py +44 -0
- async_amazon_ads_api_v1/client/sb/branded_keywords_pricings.py +24 -0
- async_amazon_ads_api_v1/client/sb/campaigns.py +41 -0
- async_amazon_ads_api_v1/client/sb/keyword_reservation_validations.py +24 -0
- async_amazon_ads_api_v1/client/sb/recommendation_types.py +26 -0
- async_amazon_ads_api_v1/client/sb/recommendations.py +24 -0
- async_amazon_ads_api_v1/client/sb/targets.py +41 -0
- async_amazon_ads_api_v1/client/sd/__init__.py +65 -0
- async_amazon_ads_api_v1/client/sd/ad_groups.py +41 -0
- async_amazon_ads_api_v1/client/sd/ads.py +37 -0
- async_amazon_ads_api_v1/client/sd/campaigns.py +41 -0
- async_amazon_ads_api_v1/client/sd/targets.py +41 -0
- async_amazon_ads_api_v1/client/sp/__init__.py +73 -0
- async_amazon_ads_api_v1/client/sp/ad_extensions.py +40 -0
- async_amazon_ads_api_v1/client/sp/ad_groups.py +43 -0
- async_amazon_ads_api_v1/client/sp/ads.py +39 -0
- async_amazon_ads_api_v1/client/sp/campaigns.py +43 -0
- async_amazon_ads_api_v1/client/sp/targets.py +43 -0
- async_amazon_ads_api_v1/config/__init__.py +1 -0
- async_amazon_ads_api_v1/config/loader.py +82 -0
- async_amazon_ads_api_v1/config/region.py +20 -0
- async_amazon_ads_api_v1/config/settings.py +136 -0
- async_amazon_ads_api_v1/config/token_cache.py +192 -0
- async_amazon_ads_api_v1/config/token_manager.py +124 -0
- async_amazon_ads_api_v1/errors.py +144 -0
- async_amazon_ads_api_v1/models/base.py +3 -0
- async_amazon_ads_api_v1/models/sb/__init__.py +34 -0
- async_amazon_ads_api_v1/models/sb/ad_extensions.py +262 -0
- async_amazon_ads_api_v1/models/sb/ad_groups.py +197 -0
- async_amazon_ads_api_v1/models/sb/ads.py +973 -0
- async_amazon_ads_api_v1/models/sb/advertising_deal_targets.py +153 -0
- async_amazon_ads_api_v1/models/sb/advertising_deals.py +220 -0
- async_amazon_ads_api_v1/models/sb/branded_keywords_pricings.py +96 -0
- async_amazon_ads_api_v1/models/sb/campaigns.py +724 -0
- async_amazon_ads_api_v1/models/sb/enums.py +205 -0
- async_amazon_ads_api_v1/models/sb/keyword_reservation_validations.py +67 -0
- async_amazon_ads_api_v1/models/sb/recommendation_types.py +37 -0
- async_amazon_ads_api_v1/models/sb/recommendations.py +177 -0
- async_amazon_ads_api_v1/models/sb/shared.py +176 -0
- async_amazon_ads_api_v1/models/sb/targets.py +585 -0
- async_amazon_ads_api_v1/models/sd/__init__.py +27 -0
- async_amazon_ads_api_v1/models/sd/ad_groups.py +348 -0
- async_amazon_ads_api_v1/models/sd/ads.py +518 -0
- async_amazon_ads_api_v1/models/sd/campaigns.py +413 -0
- async_amazon_ads_api_v1/models/sd/enums.py +193 -0
- async_amazon_ads_api_v1/models/sd/shared.py +97 -0
- async_amazon_ads_api_v1/models/sd/targets.py +661 -0
- async_amazon_ads_api_v1/models/sp/__init__.py +28 -0
- async_amazon_ads_api_v1/models/sp/ad_extensions.py +300 -0
- async_amazon_ads_api_v1/models/sp/ad_groups.py +275 -0
- async_amazon_ads_api_v1/models/sp/ads.py +390 -0
- async_amazon_ads_api_v1/models/sp/campaigns.py +706 -0
- async_amazon_ads_api_v1/models/sp/enums.py +197 -0
- async_amazon_ads_api_v1/models/sp/shared.py +217 -0
- async_amazon_ads_api_v1/models/sp/targets.py +668 -0
- async_amazon_ads_api_v1/py.typed +0 -0
- async_amazon_ads_api_v1-0.3.0.dist-info/METADATA +197 -0
- async_amazon_ads_api_v1-0.3.0.dist-info/RECORD +67 -0
- async_amazon_ads_api_v1-0.3.0.dist-info/WHEEL +4 -0
- async_amazon_ads_api_v1-0.3.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""Pure async Amazon Ads API v1 client — Sponsored Products, Sponsored Brands, Sponsored Display."""
|
|
2
|
+
|
|
3
|
+
from async_amazon_ads_api_v1.client.sb import SBClient
|
|
4
|
+
from async_amazon_ads_api_v1.client.sd import SDClient
|
|
5
|
+
from async_amazon_ads_api_v1.client.sp import SPClient
|
|
6
|
+
from async_amazon_ads_api_v1.config.region import Region
|
|
7
|
+
from async_amazon_ads_api_v1.config.settings import AmazonAdsConfig, CacheBackend
|
|
8
|
+
from async_amazon_ads_api_v1.config.token_cache import (
|
|
9
|
+
BaseTokenCache,
|
|
10
|
+
FileTokenCache,
|
|
11
|
+
RedisTokenCache,
|
|
12
|
+
close_all_redis,
|
|
13
|
+
)
|
|
14
|
+
from async_amazon_ads_api_v1.config.token_manager import TokenCredentials, TokenManager
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AmazonAdsConfig",
|
|
18
|
+
"BaseTokenCache",
|
|
19
|
+
"CacheBackend",
|
|
20
|
+
"FileTokenCache",
|
|
21
|
+
"RedisTokenCache",
|
|
22
|
+
"Region",
|
|
23
|
+
"SBClient",
|
|
24
|
+
"SDClient",
|
|
25
|
+
"SPClient",
|
|
26
|
+
"TokenCredentials",
|
|
27
|
+
"TokenManager",
|
|
28
|
+
"close_all_redis",
|
|
29
|
+
]
|
|
30
|
+
__version__ = "0.3.0"
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""Shared HTTP session and base resource class for all API resource classes."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
import logging
|
|
7
|
+
import random
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from typing import Any, TypeVar, cast
|
|
10
|
+
|
|
11
|
+
import httpx
|
|
12
|
+
from pydantic import BaseModel, ValidationError
|
|
13
|
+
|
|
14
|
+
from .config.settings import AmazonAdsConfig
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
_T = TypeVar("_T", bound=BaseModel)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ClientContext:
|
|
22
|
+
"""Shared HTTP state for all resource instances.
|
|
23
|
+
|
|
24
|
+
Lazily creates and caches the ``httpx.AsyncClient`` on first use.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
__slots__ = ("config", "_client")
|
|
28
|
+
|
|
29
|
+
def __init__(self, config: AmazonAdsConfig) -> None:
|
|
30
|
+
self.config: AmazonAdsConfig = config
|
|
31
|
+
self._client: httpx.AsyncClient | None = None
|
|
32
|
+
|
|
33
|
+
async def get_client(self) -> httpx.AsyncClient:
|
|
34
|
+
if self._client is None:
|
|
35
|
+
self._client = httpx.AsyncClient(
|
|
36
|
+
base_url=self.config.base_url,
|
|
37
|
+
timeout=httpx.Timeout(self.config.timeout),
|
|
38
|
+
)
|
|
39
|
+
return self._client
|
|
40
|
+
|
|
41
|
+
def _response(self, model_cls: type[_T], resp: httpx.Response) -> _T | dict[str, Any]:
|
|
42
|
+
if self.config.raw_response:
|
|
43
|
+
return cast(dict[str, Any], resp.json())
|
|
44
|
+
try:
|
|
45
|
+
return model_cls.model_validate_json(resp.content, extra="ignore")
|
|
46
|
+
except ValidationError:
|
|
47
|
+
logger.warning(
|
|
48
|
+
"Failed to validate response for %s (status=%s): %s",
|
|
49
|
+
model_cls.__name__,
|
|
50
|
+
resp.status_code,
|
|
51
|
+
resp.text,
|
|
52
|
+
)
|
|
53
|
+
raise
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@dataclass
|
|
57
|
+
class _ResourceSpec:
|
|
58
|
+
"""Metadata for a REST resource (campaigns, adGroups, etc)."""
|
|
59
|
+
|
|
60
|
+
name: str
|
|
61
|
+
create_model: type[BaseModel]
|
|
62
|
+
update_model: type[BaseModel] | None = None
|
|
63
|
+
delete_key: str | None = None
|
|
64
|
+
path_suffix: str = ""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class _ResourceBase:
|
|
68
|
+
"""Base class providing shared HTTP operations for resource classes."""
|
|
69
|
+
|
|
70
|
+
__slots__ = ("_ctx",)
|
|
71
|
+
|
|
72
|
+
def __init__(self, ctx: ClientContext) -> None:
|
|
73
|
+
self._ctx: ClientContext = ctx
|
|
74
|
+
|
|
75
|
+
async def _request(
|
|
76
|
+
self,
|
|
77
|
+
method: str,
|
|
78
|
+
path: str,
|
|
79
|
+
*,
|
|
80
|
+
params: dict[str, Any] | None = None,
|
|
81
|
+
json: dict[str, Any] | None = None,
|
|
82
|
+
accept_async: bool = False,
|
|
83
|
+
) -> httpx.Response:
|
|
84
|
+
client = await self._ctx.get_client()
|
|
85
|
+
accept = "application/vnd.createasyncrequestresults.v3+json" if accept_async else "application/json"
|
|
86
|
+
if self._ctx.config.access_token is None and self._ctx.config.refresh_token:
|
|
87
|
+
await self._ctx.config.refresh_access_token()
|
|
88
|
+
headers = {
|
|
89
|
+
"Authorization": f"Bearer {self._ctx.config.access_token}",
|
|
90
|
+
"Accept": accept,
|
|
91
|
+
"Amazon-Ads-ClientId": self._ctx.config.client_id,
|
|
92
|
+
}
|
|
93
|
+
if self._ctx.config.profile_id is not None:
|
|
94
|
+
headers["Amazon-Advertising-API-Scope"] = self._ctx.config.profile_id
|
|
95
|
+
for attempt in range(self._ctx.config.max_retries):
|
|
96
|
+
try:
|
|
97
|
+
resp = await client.request(
|
|
98
|
+
method=method,
|
|
99
|
+
url=path,
|
|
100
|
+
params=params,
|
|
101
|
+
json=json,
|
|
102
|
+
headers=headers,
|
|
103
|
+
)
|
|
104
|
+
resp.raise_for_status()
|
|
105
|
+
return resp
|
|
106
|
+
except httpx.HTTPStatusError as exc:
|
|
107
|
+
if exc.response.status_code == 401 and self._ctx.config.refresh_token and attempt == 0:
|
|
108
|
+
await self._ctx.config.refresh_access_token()
|
|
109
|
+
headers["Authorization"] = f"Bearer {self._ctx.config.access_token}"
|
|
110
|
+
continue
|
|
111
|
+
if exc.response.status_code in (429, 503, 504):
|
|
112
|
+
if attempt < self._ctx.config.max_retries - 1:
|
|
113
|
+
wait_time = 2**attempt + random.uniform(0, 1)
|
|
114
|
+
logger.warning(f"Rate limit exceeded, retrying in %.2f seconds {exc}", wait_time)
|
|
115
|
+
await asyncio.sleep(wait_time)
|
|
116
|
+
continue
|
|
117
|
+
logger.error(f"{exc.response.status_code} {exc.response.text}")
|
|
118
|
+
raise
|
|
119
|
+
except httpx.ConnectError:
|
|
120
|
+
if attempt < self._ctx.config.max_retries - 1:
|
|
121
|
+
await asyncio.sleep(2**attempt + random.uniform(0, 1))
|
|
122
|
+
continue
|
|
123
|
+
raise
|
|
124
|
+
raise RuntimeError("Retry loop exited unexpectedly")
|
|
125
|
+
|
|
126
|
+
def _response(self, model_cls: type[_T], resp: httpx.Response) -> _T | dict[str, Any]:
|
|
127
|
+
return self._ctx._response(model_cls, resp)
|
|
128
|
+
|
|
129
|
+
def _validate(self, items: list[Any], model_cls: type[_T]) -> list[dict[str, Any]]:
|
|
130
|
+
result: list[dict[str, Any]] = []
|
|
131
|
+
for item in items:
|
|
132
|
+
if isinstance(item, model_cls):
|
|
133
|
+
result.append(item.model_dump(mode="json", exclude_none=True))
|
|
134
|
+
else:
|
|
135
|
+
result.append(model_cls(**item).model_dump(mode="json", exclude_none=True))
|
|
136
|
+
return result
|
|
137
|
+
|
|
138
|
+
async def _create(self, items: list[Any], spec: _ResourceSpec, response_cls: type[_T]) -> _T | dict[str, Any]:
|
|
139
|
+
validated = self._validate(items, spec.create_model)
|
|
140
|
+
resp = await self._request(
|
|
141
|
+
"POST",
|
|
142
|
+
f"/adsApi/v1/create/{spec.name}{spec.path_suffix}",
|
|
143
|
+
json={spec.name: validated},
|
|
144
|
+
accept_async=True,
|
|
145
|
+
)
|
|
146
|
+
return self._response(response_cls, resp)
|
|
147
|
+
|
|
148
|
+
async def _update(self, items: list[Any], spec: _ResourceSpec, response_cls: type[_T]) -> _T | dict[str, Any]:
|
|
149
|
+
assert spec.update_model is not None, f"{spec.name} has no update model"
|
|
150
|
+
validated = self._validate(items, spec.update_model)
|
|
151
|
+
resp = await self._request(
|
|
152
|
+
"POST",
|
|
153
|
+
f"/adsApi/v1/update/{spec.name}{spec.path_suffix}",
|
|
154
|
+
json={spec.name: validated},
|
|
155
|
+
accept_async=True,
|
|
156
|
+
)
|
|
157
|
+
return self._response(response_cls, resp)
|
|
158
|
+
|
|
159
|
+
async def _delete(self, ids: list[str], spec: _ResourceSpec, response_cls: type[_T]) -> _T | dict[str, Any]:
|
|
160
|
+
assert spec.delete_key is not None, f"{spec.name} has no delete operation"
|
|
161
|
+
resp = await self._request(
|
|
162
|
+
"POST",
|
|
163
|
+
f"/adsApi/v1/delete/{spec.name}{spec.path_suffix}",
|
|
164
|
+
json={spec.delete_key: ids},
|
|
165
|
+
accept_async=True,
|
|
166
|
+
)
|
|
167
|
+
return self._response(response_cls, resp)
|
|
168
|
+
|
|
169
|
+
async def _query(self, body: BaseModel, path: str, response_cls: type[_T]) -> _T | dict[str, Any]:
|
|
170
|
+
resp = await self._request("POST", path, json=body.model_dump(exclude_none=True))
|
|
171
|
+
return self._response(response_cls, resp)
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""Sponsored Brands async HTTP client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import ClientContext
|
|
8
|
+
from async_amazon_ads_api_v1.config.settings import AmazonAdsConfig
|
|
9
|
+
|
|
10
|
+
from .ad_extensions import AdExtensions
|
|
11
|
+
from .ad_groups import AdGroups
|
|
12
|
+
from .ads import Ads
|
|
13
|
+
from .advertising_deal_targets import AdvertisingDealTargets
|
|
14
|
+
from .advertising_deals import AdvertisingDeals
|
|
15
|
+
from .branded_keywords_pricings import BrandedKeywordsPricings
|
|
16
|
+
from .campaigns import Campaigns
|
|
17
|
+
from .keyword_reservation_validations import KeywordReservationValidations
|
|
18
|
+
from .recommendation_types import RecommendationTypes
|
|
19
|
+
from .recommendations import Recommendations
|
|
20
|
+
from .targets import Targets
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class SBClient:
|
|
24
|
+
"""Async HTTP client for Amazon Ads Sponsored Brands API.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
config : AmazonAdsConfig
|
|
29
|
+
Client configuration (auth, region, timeouts, retries).
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def __init__(self, config: AmazonAdsConfig) -> None:
|
|
33
|
+
self._ctx = ClientContext(config)
|
|
34
|
+
self.__campaign: Campaigns | None = None
|
|
35
|
+
self.__ad_group: AdGroups | None = None
|
|
36
|
+
self.__ad: Ads | None = None
|
|
37
|
+
self.__target: Targets | None = None
|
|
38
|
+
self.__ad_extension: AdExtensions | None = None
|
|
39
|
+
self.__advertising_deal_target: AdvertisingDealTargets | None = None
|
|
40
|
+
self.__advertising_deal: AdvertisingDeals | None = None
|
|
41
|
+
self.__branded_keywords_pricing: BrandedKeywordsPricings | None = None
|
|
42
|
+
self.__keyword_reservation_validation: KeywordReservationValidations | None = None
|
|
43
|
+
self.__recommendation_type: RecommendationTypes | None = None
|
|
44
|
+
self.__recommendation: Recommendations | None = None
|
|
45
|
+
|
|
46
|
+
async def __aenter__(self) -> SBClient:
|
|
47
|
+
return self
|
|
48
|
+
|
|
49
|
+
async def __aexit__(self, *args: Any) -> None:
|
|
50
|
+
await self.close()
|
|
51
|
+
|
|
52
|
+
async def close(self) -> None:
|
|
53
|
+
if self._ctx._client is not None:
|
|
54
|
+
await self._ctx._client.aclose()
|
|
55
|
+
self._ctx._client = None
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def campaigns(self) -> Campaigns:
|
|
59
|
+
if self.__campaign is None:
|
|
60
|
+
self.__campaign = Campaigns(self._ctx)
|
|
61
|
+
return self.__campaign
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def ad_groups(self) -> AdGroups:
|
|
65
|
+
if self.__ad_group is None:
|
|
66
|
+
self.__ad_group = AdGroups(self._ctx)
|
|
67
|
+
return self.__ad_group
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def ads(self) -> Ads:
|
|
71
|
+
if self.__ad is None:
|
|
72
|
+
self.__ad = Ads(self._ctx)
|
|
73
|
+
return self.__ad
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def targets(self) -> Targets:
|
|
77
|
+
if self.__target is None:
|
|
78
|
+
self.__target = Targets(self._ctx)
|
|
79
|
+
return self.__target
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def ad_extensions(self) -> AdExtensions:
|
|
83
|
+
if self.__ad_extension is None:
|
|
84
|
+
self.__ad_extension = AdExtensions(self._ctx)
|
|
85
|
+
return self.__ad_extension
|
|
86
|
+
|
|
87
|
+
@property
|
|
88
|
+
def advertising_deal_targets(self) -> AdvertisingDealTargets:
|
|
89
|
+
if self.__advertising_deal_target is None:
|
|
90
|
+
self.__advertising_deal_target = AdvertisingDealTargets(self._ctx)
|
|
91
|
+
return self.__advertising_deal_target
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def advertising_deals(self) -> AdvertisingDeals:
|
|
95
|
+
if self.__advertising_deal is None:
|
|
96
|
+
self.__advertising_deal = AdvertisingDeals(self._ctx)
|
|
97
|
+
return self.__advertising_deal
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def branded_keywords_pricings(self) -> BrandedKeywordsPricings:
|
|
101
|
+
if self.__branded_keywords_pricing is None:
|
|
102
|
+
self.__branded_keywords_pricing = BrandedKeywordsPricings(self._ctx)
|
|
103
|
+
return self.__branded_keywords_pricing
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def keyword_reservation_validations(self) -> KeywordReservationValidations:
|
|
107
|
+
if self.__keyword_reservation_validation is None:
|
|
108
|
+
self.__keyword_reservation_validation = KeywordReservationValidations(self._ctx)
|
|
109
|
+
return self.__keyword_reservation_validation
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def recommendation_types(self) -> RecommendationTypes:
|
|
113
|
+
if self.__recommendation_type is None:
|
|
114
|
+
self.__recommendation_type = RecommendationTypes(self._ctx)
|
|
115
|
+
return self.__recommendation_type
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def recommendations(self) -> Recommendations:
|
|
119
|
+
if self.__recommendation is None:
|
|
120
|
+
self.__recommendation = Recommendations(self._ctx)
|
|
121
|
+
return self.__recommendation
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""SB AdExtension resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBAdExtensionCreate,
|
|
10
|
+
SBAdExtensionMultiStatusResponse,
|
|
11
|
+
SBAdExtensionSuccessResponse,
|
|
12
|
+
SBAdExtensionUpdate,
|
|
13
|
+
SBQueryAdExtensionRequest,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AdExtensions(_ResourceBase):
|
|
18
|
+
_spec = _ResourceSpec(
|
|
19
|
+
name="adExtensions",
|
|
20
|
+
create_model=SBAdExtensionCreate,
|
|
21
|
+
update_model=SBAdExtensionUpdate,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
async def create(
|
|
25
|
+
self, ad_extensions: list[dict[str, Any] | SBAdExtensionCreate]
|
|
26
|
+
) -> SBAdExtensionSuccessResponse | dict[str, Any]:
|
|
27
|
+
return await self._create(ad_extensions, self._spec, SBAdExtensionSuccessResponse)
|
|
28
|
+
|
|
29
|
+
async def query(
|
|
30
|
+
self, body: dict[str, Any] | SBQueryAdExtensionRequest
|
|
31
|
+
) -> SBAdExtensionSuccessResponse | dict[str, Any]:
|
|
32
|
+
if isinstance(body, dict):
|
|
33
|
+
body = SBQueryAdExtensionRequest(**body)
|
|
34
|
+
return await self._query(body, "/adsApi/v1/query/adExtensions", SBAdExtensionSuccessResponse)
|
|
35
|
+
|
|
36
|
+
async def update(
|
|
37
|
+
self, ad_extensions: list[dict[str, Any] | SBAdExtensionUpdate]
|
|
38
|
+
) -> SBAdExtensionMultiStatusResponse | dict[str, Any]:
|
|
39
|
+
return await self._update(ad_extensions, self._spec, SBAdExtensionMultiStatusResponse)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""SB AdGroup resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBAdGroupCreate,
|
|
10
|
+
SBAdGroupMultiStatusResponse,
|
|
11
|
+
SBAdGroupSuccessResponse,
|
|
12
|
+
SBAdGroupUpdate,
|
|
13
|
+
SBQueryAdGroupRequest,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AdGroups(_ResourceBase):
|
|
18
|
+
_spec = _ResourceSpec(
|
|
19
|
+
name="adGroups",
|
|
20
|
+
create_model=SBAdGroupCreate,
|
|
21
|
+
update_model=SBAdGroupUpdate,
|
|
22
|
+
delete_key="adGroupIds",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
async def create(
|
|
26
|
+
self, ad_groups: list[dict[str, Any] | SBAdGroupCreate]
|
|
27
|
+
) -> SBAdGroupMultiStatusResponse | dict[str, Any]:
|
|
28
|
+
return await self._create(ad_groups, self._spec, SBAdGroupMultiStatusResponse)
|
|
29
|
+
|
|
30
|
+
async def query(self, body: dict[str, Any] | SBQueryAdGroupRequest) -> SBAdGroupSuccessResponse | dict[str, Any]:
|
|
31
|
+
if isinstance(body, dict):
|
|
32
|
+
body = SBQueryAdGroupRequest(**body)
|
|
33
|
+
return await self._query(body, "/adsApi/v1/query/adGroups", SBAdGroupSuccessResponse)
|
|
34
|
+
|
|
35
|
+
async def update(
|
|
36
|
+
self, ad_groups: list[dict[str, Any] | SBAdGroupUpdate]
|
|
37
|
+
) -> SBAdGroupMultiStatusResponse | dict[str, Any]:
|
|
38
|
+
return await self._update(ad_groups, self._spec, SBAdGroupMultiStatusResponse)
|
|
39
|
+
|
|
40
|
+
async def delete(self, ad_group_ids: list[str]) -> SBAdGroupMultiStatusResponse | dict[str, Any]:
|
|
41
|
+
return await self._delete(ad_group_ids, self._spec, SBAdGroupMultiStatusResponse)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"""SB Ad resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBAdCreate,
|
|
10
|
+
SBAdMultiStatusResponse,
|
|
11
|
+
SBAdSuccessResponse,
|
|
12
|
+
SBAdUpdate,
|
|
13
|
+
SBQueryAdRequest,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Ads(_ResourceBase):
|
|
18
|
+
_spec = _ResourceSpec(
|
|
19
|
+
name="ads",
|
|
20
|
+
create_model=SBAdCreate,
|
|
21
|
+
update_model=SBAdUpdate,
|
|
22
|
+
delete_key="adIds",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
async def create(self, ads: list[dict[str, Any] | SBAdCreate]) -> SBAdMultiStatusResponse | dict[str, Any]:
|
|
26
|
+
return await self._create(ads, self._spec, SBAdMultiStatusResponse)
|
|
27
|
+
|
|
28
|
+
async def query(self, body: dict[str, Any] | SBQueryAdRequest) -> SBAdSuccessResponse | dict[str, Any]:
|
|
29
|
+
if isinstance(body, dict):
|
|
30
|
+
body = SBQueryAdRequest(**body)
|
|
31
|
+
return await self._query(body, "/adsApi/v1/query/ads", SBAdSuccessResponse)
|
|
32
|
+
|
|
33
|
+
async def update(self, ads: list[dict[str, Any] | SBAdUpdate]) -> SBAdMultiStatusResponse | dict[str, Any]:
|
|
34
|
+
return await self._update(ads, self._spec, SBAdMultiStatusResponse)
|
|
35
|
+
|
|
36
|
+
async def delete(self, ad_ids: list[str]) -> SBAdMultiStatusResponse | dict[str, Any]:
|
|
37
|
+
return await self._delete(ad_ids, self._spec, SBAdMultiStatusResponse)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""SB AdvertisingDealTarget resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBAdvertisingDealTargetCreate,
|
|
10
|
+
SBAdvertisingDealTargetMultiStatusResponse,
|
|
11
|
+
SBAdvertisingDealTargetSuccessResponse,
|
|
12
|
+
SBQueryAdvertisingDealTargetRequest,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AdvertisingDealTargets(_ResourceBase):
|
|
17
|
+
_spec = _ResourceSpec(
|
|
18
|
+
name="advertisingDealTargets",
|
|
19
|
+
create_model=SBAdvertisingDealTargetCreate,
|
|
20
|
+
delete_key="advertisingDealTargetIds",
|
|
21
|
+
path_suffix="/sb",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
async def create(
|
|
25
|
+
self, items: list[dict[str, Any] | SBAdvertisingDealTargetCreate]
|
|
26
|
+
) -> SBAdvertisingDealTargetSuccessResponse | dict[str, Any]:
|
|
27
|
+
return await self._create(items, self._spec, SBAdvertisingDealTargetSuccessResponse)
|
|
28
|
+
|
|
29
|
+
async def query(
|
|
30
|
+
self, body: dict[str, Any] | SBQueryAdvertisingDealTargetRequest
|
|
31
|
+
) -> SBAdvertisingDealTargetSuccessResponse | dict[str, Any]:
|
|
32
|
+
if isinstance(body, dict):
|
|
33
|
+
body = SBQueryAdvertisingDealTargetRequest(**body)
|
|
34
|
+
return await self._query(
|
|
35
|
+
body,
|
|
36
|
+
"/adsApi/v1/query/advertisingDealTargets/sb",
|
|
37
|
+
SBAdvertisingDealTargetSuccessResponse,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
async def delete(self, ids: list[str]) -> SBAdvertisingDealTargetMultiStatusResponse | dict[str, Any]:
|
|
41
|
+
return await self._delete(ids, self._spec, SBAdvertisingDealTargetMultiStatusResponse)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""SB AdvertisingDeal resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBAdvertisingDealCreate,
|
|
10
|
+
SBAdvertisingDealMultiStatusResponse,
|
|
11
|
+
SBAdvertisingDealSuccessResponse,
|
|
12
|
+
SBAdvertisingDealUpdate,
|
|
13
|
+
SBQueryAdvertisingDealRequest,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class AdvertisingDeals(_ResourceBase):
|
|
18
|
+
_spec = _ResourceSpec(
|
|
19
|
+
name="advertisingDeals",
|
|
20
|
+
create_model=SBAdvertisingDealCreate,
|
|
21
|
+
update_model=SBAdvertisingDealUpdate,
|
|
22
|
+
delete_key="advertisingDealIds",
|
|
23
|
+
path_suffix="/sb",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
async def create(
|
|
27
|
+
self, items: list[dict[str, Any] | SBAdvertisingDealCreate]
|
|
28
|
+
) -> SBAdvertisingDealSuccessResponse | dict[str, Any]:
|
|
29
|
+
return await self._create(items, self._spec, SBAdvertisingDealSuccessResponse)
|
|
30
|
+
|
|
31
|
+
async def query(
|
|
32
|
+
self, body: dict[str, Any] | SBQueryAdvertisingDealRequest
|
|
33
|
+
) -> SBAdvertisingDealSuccessResponse | dict[str, Any]:
|
|
34
|
+
if isinstance(body, dict):
|
|
35
|
+
body = SBQueryAdvertisingDealRequest(**body)
|
|
36
|
+
return await self._query(body, "/adsApi/v1/query/advertisingDeals/sb", SBAdvertisingDealSuccessResponse)
|
|
37
|
+
|
|
38
|
+
async def update(
|
|
39
|
+
self, items: list[dict[str, Any] | SBAdvertisingDealUpdate]
|
|
40
|
+
) -> SBAdvertisingDealMultiStatusResponse | dict[str, Any]:
|
|
41
|
+
return await self._update(items, self._spec, SBAdvertisingDealMultiStatusResponse)
|
|
42
|
+
|
|
43
|
+
async def delete(self, ids: list[str]) -> SBAdvertisingDealMultiStatusResponse | dict[str, Any]:
|
|
44
|
+
return await self._delete(ids, self._spec, SBAdvertisingDealMultiStatusResponse)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""SB BrandedKeywordsPricing resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBBrandedKeywordsPricingCreate,
|
|
10
|
+
SBBrandedKeywordsPricingMultiStatusResponse,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BrandedKeywordsPricings(_ResourceBase):
|
|
15
|
+
_spec = _ResourceSpec(
|
|
16
|
+
name="brandedKeywordsPricings",
|
|
17
|
+
create_model=SBBrandedKeywordsPricingCreate,
|
|
18
|
+
path_suffix="/sb",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
async def create(
|
|
22
|
+
self, items: list[dict[str, Any] | SBBrandedKeywordsPricingCreate]
|
|
23
|
+
) -> SBBrandedKeywordsPricingMultiStatusResponse | dict[str, Any]:
|
|
24
|
+
return await self._create(items, self._spec, SBBrandedKeywordsPricingMultiStatusResponse)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""SB Campaign resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBCampaignCreate,
|
|
10
|
+
SBCampaignMultiStatusResponse,
|
|
11
|
+
SBCampaignSuccessResponse,
|
|
12
|
+
SBCampaignUpdate,
|
|
13
|
+
SBQueryCampaignRequest,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Campaigns(_ResourceBase):
|
|
18
|
+
_spec = _ResourceSpec(
|
|
19
|
+
name="campaigns",
|
|
20
|
+
create_model=SBCampaignCreate,
|
|
21
|
+
update_model=SBCampaignUpdate,
|
|
22
|
+
delete_key="campaignIds",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
async def create(
|
|
26
|
+
self, campaigns: list[dict[str, Any] | SBCampaignCreate]
|
|
27
|
+
) -> SBCampaignMultiStatusResponse | dict[str, Any]:
|
|
28
|
+
return await self._create(campaigns, self._spec, SBCampaignMultiStatusResponse)
|
|
29
|
+
|
|
30
|
+
async def query(self, body: dict[str, Any] | SBQueryCampaignRequest) -> SBCampaignSuccessResponse | dict[str, Any]:
|
|
31
|
+
if isinstance(body, dict):
|
|
32
|
+
body = SBQueryCampaignRequest(**body)
|
|
33
|
+
return await self._query(body, "/adsApi/v1/query/campaigns", SBCampaignSuccessResponse)
|
|
34
|
+
|
|
35
|
+
async def update(
|
|
36
|
+
self, campaigns: list[dict[str, Any] | SBCampaignUpdate]
|
|
37
|
+
) -> SBCampaignMultiStatusResponse | dict[str, Any]:
|
|
38
|
+
return await self._update(campaigns, self._spec, SBCampaignMultiStatusResponse)
|
|
39
|
+
|
|
40
|
+
async def delete(self, campaign_ids: list[str]) -> SBCampaignMultiStatusResponse | dict[str, Any]:
|
|
41
|
+
return await self._delete(campaign_ids, self._spec, SBCampaignMultiStatusResponse)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""SB KeywordReservationValidation resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBKeywordReservationValidationCreate,
|
|
10
|
+
SBKeywordReservationValidationMultiStatusResponse,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class KeywordReservationValidations(_ResourceBase):
|
|
15
|
+
_spec = _ResourceSpec(
|
|
16
|
+
name="keywordReservationValidations",
|
|
17
|
+
create_model=SBKeywordReservationValidationCreate,
|
|
18
|
+
path_suffix="/sb",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
async def create(
|
|
22
|
+
self, items: list[dict[str, Any] | SBKeywordReservationValidationCreate]
|
|
23
|
+
) -> SBKeywordReservationValidationMultiStatusResponse | dict[str, Any]:
|
|
24
|
+
return await self._create(items, self._spec, SBKeywordReservationValidationMultiStatusResponse)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""SB RecommendationType resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBQueryRecommendationTypeRequest,
|
|
10
|
+
SBRecommendationTypeSuccessResponse,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class RecommendationTypes(_ResourceBase):
|
|
15
|
+
_spec = _ResourceSpec(
|
|
16
|
+
name="recommendationTypes",
|
|
17
|
+
create_model=SBRecommendationTypeSuccessResponse,
|
|
18
|
+
path_suffix="/sb",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
async def query(
|
|
22
|
+
self, body: dict[str, Any] | SBQueryRecommendationTypeRequest
|
|
23
|
+
) -> SBRecommendationTypeSuccessResponse | dict[str, Any]:
|
|
24
|
+
if isinstance(body, dict):
|
|
25
|
+
body = SBQueryRecommendationTypeRequest(**body)
|
|
26
|
+
return await self._query(body, "/adsApi/v1/query/recommendationTypes/sb", SBRecommendationTypeSuccessResponse)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""SB Recommendation resource operations."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from async_amazon_ads_api_v1._base import _ResourceBase, _ResourceSpec
|
|
8
|
+
from async_amazon_ads_api_v1.models.sb import (
|
|
9
|
+
SBRecommendationCreate,
|
|
10
|
+
SBRecommendationMultiStatusResponse,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Recommendations(_ResourceBase):
|
|
15
|
+
_spec = _ResourceSpec(
|
|
16
|
+
name="recommendations",
|
|
17
|
+
create_model=SBRecommendationCreate,
|
|
18
|
+
path_suffix="/sb",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
async def create(
|
|
22
|
+
self, items: list[dict[str, Any] | SBRecommendationCreate]
|
|
23
|
+
) -> SBRecommendationMultiStatusResponse | dict[str, Any]:
|
|
24
|
+
return await self._create(items, self._spec, SBRecommendationMultiStatusResponse)
|