python-amazon-ad-api 1.1.1__py3-none-any.whl → 1.1.3__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.
ad_api/api/sb/__init__.py CHANGED
@@ -20,6 +20,7 @@ from .media import Media
20
20
  from .reports import Reports
21
21
  from .benchmarks import Benchmarks
22
22
  from .themes import Themes
23
+ from .budget_rules import BudgetRules
23
24
 
24
25
  __all__ = [
25
26
  "Brands",
@@ -43,5 +44,6 @@ __all__ = [
43
44
  "Media",
44
45
  "Reports",
45
46
  "Benchmarks",
46
- "Themes"
47
+ "Themes",
48
+ "BudgetRules",
47
49
  ]
@@ -0,0 +1,235 @@
1
+ from ad_api.base import Client, sp_endpoint, fill_query_params, ApiResponse, Utils
2
+
3
+
4
+ class BudgetRules(Client):
5
+ """Sponsored Brands budget rules.
6
+
7
+ Documentation: https://advertising.amazon.com/API/docs/en-us/sponsored-brands/4-0/openapi
8
+
9
+ Read routes were probed against the live service; the write routes are built
10
+ from the contract and not exercised, because they change campaign budgets.
11
+
12
+ .. note::
13
+ ``budget_recommendations`` only answers with the versioned media type.
14
+ Sending ``application/json`` makes the router answer ``404 Could not find
15
+ resource``, as if the route did not exist. Amazon routes on media type.
16
+
17
+ .. note::
18
+ An unknown ``budgetRuleId`` answers ``400 InvalidParameterValue`` with
19
+ ``errorCode 240002``, not a 404. The identifier is validated before it is
20
+ looked up.
21
+ """
22
+
23
+ _MEDIA_JSON = 'application/json'
24
+ _MEDIA_USAGE = 'application/vnd.sbcampaignbudgetusage.v1+json'
25
+ _MEDIA_RECS = 'application/vnd.sbbudgetrecommendation.v4+json'
26
+
27
+ @sp_endpoint('/sb/budgetRules', method='GET')
28
+ def list_budget_rules(self, pageSize, **kwargs) -> ApiResponse:
29
+ """
30
+ Gets the budget rules of the advertiser.
31
+
32
+ Keyword Args
33
+ | query **pageSize** (number): [required] Results per page.
34
+ | query **nextToken** (string): Pagination token. [optional]
35
+
36
+ Returns:
37
+ | ApiResponse, with the rules under ``budgetRulesForAdvertiserResponse``
38
+ and a ``nextToken``.
39
+ """
40
+ return self._request(kwargs.pop('path'), params=kwargs,
41
+ headers={'Accept': self._MEDIA_JSON})
42
+
43
+ @sp_endpoint('/sb/budgetRules/{}', method='GET')
44
+ def get_budget_rule(self, budgetRuleId, **kwargs) -> ApiResponse:
45
+ """
46
+ Gets one budget rule by identifier.
47
+
48
+ Keyword Args
49
+ | path **budgetRuleId** (string): [required]
50
+ """
51
+ return self._request(fill_query_params(kwargs.pop('path'), budgetRuleId),
52
+ params=kwargs, headers={'Accept': self._MEDIA_JSON})
53
+
54
+ @sp_endpoint('/sb/budgetRules/{}/campaigns', method='GET')
55
+ def list_rule_campaigns(self, budgetRuleId, pageSize, **kwargs) -> ApiResponse:
56
+ """
57
+ Gets the campaigns associated with a budget rule.
58
+
59
+ Keyword Args
60
+ | path **budgetRuleId** (string): [required]
61
+ | query **pageSize** (number): [required]
62
+ | query **nextToken** (string): [optional]
63
+ """
64
+ return self._request(fill_query_params(kwargs.pop('path'), budgetRuleId),
65
+ params=kwargs, headers={'Accept': self._MEDIA_JSON})
66
+
67
+ @sp_endpoint('/sb/campaigns/{}/budgetRules', method='GET')
68
+ def list_campaign_rules(self, campaignId, **kwargs) -> ApiResponse:
69
+ """
70
+ Gets the budget rules associated with a campaign.
71
+
72
+ Keyword Args
73
+ | path **campaignId** (number): [required]
74
+
75
+ Returns:
76
+ | ApiResponse, with the rules under ``associatedRules``.
77
+ """
78
+ return self._request(fill_query_params(kwargs.pop('path'), campaignId),
79
+ params=kwargs, headers={'Accept': self._MEDIA_JSON})
80
+
81
+ @sp_endpoint('/sb/budgetRules', method='POST')
82
+ def create_budget_rules(self, budgetRulesDetails, **kwargs) -> ApiResponse:
83
+ """
84
+ Creates budget rules.
85
+
86
+ Request Body [Required]
87
+ | **budgetRulesDetails** (array): One entry per rule.
88
+ | **name** (string): Rule name.
89
+ | **ruleType** (string): ``SCHEDULE`` or ``PERFORMANCE``.
90
+ | **budgetIncreaseBy** ({}): ``type`` (``PERCENT``) and ``value``.
91
+ | **performanceMeasureCondition** ({}): ``metricName`` (``IS``,
92
+ ``NTB`` or ``ROAS``), ``comparisonOperator`` (``GREATER_THAN``,
93
+ ``LESS_THAN``, ``LESS_THAN_OR_EQUAL_TO``,
94
+ ``GREATER_THAN_OR_EQUAL_TO``) and ``threshold``.
95
+ | **duration** ({}): ``eventTypeRuleDuration`` with ``eventId``, or
96
+ ``dateRangeTypeRuleDuration`` with ``startDate``.
97
+ | **recurrence** ({}): ``type`` (``DAILY`` or ``WEEKLY``),
98
+ ``daysOfWeek`` and ``intraDaySchedule``.
99
+
100
+ Returns:
101
+ | ApiResponse, status ``207``.
102
+
103
+ .. note::
104
+ Not probed: creates budget rules on the account.
105
+ """
106
+ return self._request(kwargs.pop('path'),
107
+ data=Utils.convert_body({'budgetRulesDetails': budgetRulesDetails}, False),
108
+ params=kwargs, headers={'Accept': self._MEDIA_JSON,
109
+ 'Content-Type': self._MEDIA_JSON})
110
+
111
+ @sp_endpoint('/sb/budgetRules', method='PUT')
112
+ def update_budget_rules(self, budgetRulesDetails, **kwargs) -> ApiResponse:
113
+ """
114
+ Updates budget rules.
115
+
116
+ Request Body [Required]
117
+ | **budgetRulesDetails** (array): Each entry needs ``ruleId`` and may
118
+ carry ``ruleState`` (``ACTIVE`` or ``PAUSED``) and ``ruleDetails``
119
+ with the same shape used on creation.
120
+
121
+ Returns:
122
+ | ApiResponse, status ``207``.
123
+
124
+ .. note::
125
+ Not probed: updates live budget rules.
126
+ """
127
+ return self._request(kwargs.pop('path'),
128
+ data=Utils.convert_body({'budgetRulesDetails': budgetRulesDetails}, False),
129
+ params=kwargs, headers={'Accept': self._MEDIA_JSON,
130
+ 'Content-Type': self._MEDIA_JSON})
131
+
132
+ @sp_endpoint('/sb/campaigns/{}/budgetRules', method='POST')
133
+ def associate_budget_rules(self, campaignId, budgetRuleIds, **kwargs) -> ApiResponse:
134
+ """
135
+ Associates budget rules with a campaign.
136
+
137
+ Keyword Args
138
+ | path **campaignId** (number): [required]
139
+
140
+ Request Body [Required]
141
+ | **budgetRuleIds** (array of string): [required]
142
+
143
+ Returns:
144
+ | ApiResponse, status ``207``.
145
+
146
+ .. note::
147
+ Not probed: changes which rules apply to a live campaign.
148
+ """
149
+ return self._request(fill_query_params(kwargs.pop('path'), campaignId),
150
+ data=Utils.convert_body({'budgetRuleIds': budgetRuleIds}, False),
151
+ params=kwargs, headers={'Accept': self._MEDIA_JSON,
152
+ 'Content-Type': self._MEDIA_JSON})
153
+
154
+ @sp_endpoint('/sb/campaigns/{}/budgetRules/{}', method='DELETE')
155
+ def disassociate_budget_rule(self, campaignId, budgetRuleId, **kwargs) -> ApiResponse:
156
+ """
157
+ Disassociates one budget rule from a campaign.
158
+
159
+ Keyword Args
160
+ | path **campaignId** (number): [required]
161
+ | path **budgetRuleId** (string): [required]
162
+
163
+ Returns:
164
+ | ApiResponse, status ``200``.
165
+
166
+ .. note::
167
+ Not probed: changes which rules apply to a live campaign.
168
+ """
169
+ path = fill_query_params(kwargs.pop('path'), campaignId)
170
+ return self._request(fill_query_params(path, budgetRuleId),
171
+ params=kwargs, headers={'Accept': self._MEDIA_JSON})
172
+
173
+ @sp_endpoint('/sb/campaigns/budget/usage', method='POST')
174
+ def get_budget_usage(self, campaignIds, **kwargs) -> ApiResponse:
175
+ """
176
+ Gets budget usage for campaigns.
177
+
178
+ Request Body [Required]
179
+ | **campaignIds** (array of string): [required]
180
+
181
+ Returns:
182
+ | ApiResponse, with per-campaign entries under ``success`` and failures
183
+ under ``error``. Each success entry carries ``budget``,
184
+ ``budgetUsagePercent``, ``campaignId``, ``index`` and
185
+ ``usageUpdatedTimestamp``.
186
+
187
+ Example::
188
+
189
+ {"success": [{"budget": 10.0, "budgetUsagePercent": 0.0,
190
+ "campaignId": "95988386496299", "index": 0,
191
+ "usageUpdatedTimestamp": "2026-10-25T00:00:00Z"}],
192
+ "error": []}
193
+ """
194
+ return self._request(kwargs.pop('path'),
195
+ data=Utils.convert_body({'campaignIds': campaignIds}, False),
196
+ params=kwargs, headers={'Accept': self._MEDIA_USAGE,
197
+ 'Content-Type': self._MEDIA_USAGE})
198
+
199
+ @sp_endpoint('/sb/campaigns/budgetRecommendations', method='POST')
200
+ def get_budget_recommendations(self, campaignIds, **kwargs) -> ApiResponse:
201
+ """
202
+ Gets budget recommendations for campaigns.
203
+
204
+ Request Body [Required]
205
+ | **campaignIds** (array of string): [required]
206
+
207
+ Returns:
208
+ | ApiResponse, status ``207``.
209
+
210
+ .. warning::
211
+ This route only answers with its versioned media type. With
212
+ ``application/json`` the service answers ``404 Could not find
213
+ resource``, which reads like a missing route but is only the wrong
214
+ media type.
215
+ """
216
+ return self._request(kwargs.pop('path'),
217
+ data=Utils.convert_body({'campaignIds': campaignIds}, False),
218
+ params=kwargs, headers={'Accept': self._MEDIA_RECS,
219
+ 'Content-Type': self._MEDIA_RECS})
220
+
221
+ @sp_endpoint('/sb/campaigns/budgetRules/recommendations', method='POST')
222
+ def get_budget_rules_recommendation(self, **kwargs) -> ApiResponse:
223
+ """
224
+ Gets budget rule recommendations.
225
+
226
+ Returns:
227
+ | ApiResponse
228
+
229
+ .. note::
230
+ Declared in the 3.0 contract, not in 4.0. Not probed.
231
+ """
232
+ return self._request(kwargs.pop('path'),
233
+ data=Utils.convert_body(kwargs.pop('body', {}), False),
234
+ params=kwargs, headers={'Accept': self._MEDIA_JSON,
235
+ 'Content-Type': self._MEDIA_JSON})
@@ -2,6 +2,6 @@ from ad_api.base import Client, sp_endpoint, ApiResponse, Utils
2
2
 
3
3
 
4
4
  class Recommendations(Client):
5
- @sp_endpoint('/sb​/recommendations​/creative​/headline', method='POST')
5
+ @sp_endpoint('/sb/recommendations/creative/headline', method='POST')
6
6
  def list_recommendations(self, **kwargs) -> ApiResponse:
7
7
  return self._request(kwargs.pop('path'), data=Utils.convert_body(kwargs.pop('body'), False), params=kwargs)
ad_api/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "1.1.1"
1
+ __version__ = "1.1.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-amazon-ad-api
3
- Version: 1.1.1
3
+ Version: 1.1.3
4
4
  Summary: Python wrapper for the Amazon Advertising API
5
5
  Home-page: https://github.com/denisneuf/python-amazon-ad-api
6
6
  Author: Daniel Alvaro
@@ -1,5 +1,5 @@
1
1
  ad_api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- ad_api/version.py,sha256=q8_5C0f-8mHWNb6mMw02zlYPnEGXBqvOmP3z0CEwZKM,22
2
+ ad_api/version.py,sha256=u9ExJqoMv3fQc8WmLTw4I2FnQo6u4xRrBc6DLy6G1IE,22
3
3
  ad_api/api/__init__.py,sha256=E9c0ZyK4vplMlKKEBF8CV5u7P4uSkTMSQsAuSQu5bfY,1514
4
4
  ad_api/api/account.py,sha256=CmOvCfHoPWaeTUJvtB0pNoNulZVSz4oMMCKIpVTpHos,2931
5
5
  ad_api/api/advertising_test_account.py,sha256=btOVbdk2tBDmyKSJaQbcIFyzNG8KFJVUmTe4p9xMhpU,1507
@@ -24,7 +24,7 @@ ad_api/api/reports.py,sha256=gNmDHLULD2uaJgsMpIbCX9kabwhMXRr9WfZBtHUdsOY,6043
24
24
  ad_api/api/stores.py,sha256=7W3RJKZyZOQ3nHzInvK9FDhWTXCH6Xe9a6dCBatEZ-o,2484
25
25
  ad_api/api/stream.py,sha256=JpnF8SKniOAHiEnEq1RPrh6tNy-Q2-8GPBTmnlxEXqQ,2989
26
26
  ad_api/api/validation_configurations.py,sha256=V3o06uWGwvA_Ly1x2lAiCk35Wo7DC_k8AtHgMdpm6wU,3830
27
- ad_api/api/sb/__init__.py,sha256=Lb7biv_idmsN6SkObBhQS4hZs3rdeQr0ytSvcl2tfSo,1274
27
+ ad_api/api/sb/__init__.py,sha256=1M9GaWMkwb7_0G-JtgAEMjFRpsLs4Ls2-pVtFIyn9LM,1332
28
28
  ad_api/api/sb/ad_creatives_v4.py,sha256=86sF2lhSc3AC6d4P5TXyEnJMBjn9HvsJe4bbCQbSWK0,10508
29
29
  ad_api/api/sb/ad_groups.py,sha256=W06Fk0CCsuEYen1Bd8obR6aHpOMhk6tGWNWApecw59c,2882
30
30
  ad_api/api/sb/ad_groups_v4.py,sha256=f6KpOrJ2RsCa4aznP8vdGbXp0HGsCmLOvC9yXX2pESc,3669
@@ -32,6 +32,7 @@ ad_api/api/sb/ads_v4.py,sha256=EOn-ts0cPqCwt5vdGq6rkDHyYPoT6vbDP8UQE-TFjmE,7931
32
32
  ad_api/api/sb/benchmarks.py,sha256=eeWv2rrRf4ttK-oI1EEEiui_rl_sxJk9yXcu6sDSfhg,3645
33
33
  ad_api/api/sb/bid_recommendations.py,sha256=ssO9XwYC9wK2GFaLtcsC-D3cZhDpCclcu1r01LTkZAw,2297
34
34
  ad_api/api/sb/brands.py,sha256=XIMDzV0tJoPiOcY0KoCKcyIwYLPMlJ-zkB2SeRVMF4Q,1376
35
+ ad_api/api/sb/budget_rules.py,sha256=8hyJ4yD-myR4atYmTm8KsTSB5ZNfASGe2fxgwRv4SRs,10029
35
36
  ad_api/api/sb/campaigns.py,sha256=41yRnrgvx4-9Zra7Zdqtzr2Ptq__YD-mHOWbACaEQOk,13674
36
37
  ad_api/api/sb/campaigns_v4.py,sha256=_SfEQhHCS90UaSxOq35mm7NAr2BVpqJ4gzAbauVCZiA,7290
37
38
  ad_api/api/sb/forecast.py,sha256=qf2ivhGX3_dv_uMGP9cmrt_x3S7QLg-P_5nCI8bAr00,3967
@@ -42,7 +43,7 @@ ad_api/api/sb/media.py,sha256=5LTeM4AHSDKw_58aTB2nEZhIYdWkztH0syBXaovS1rs,2529
42
43
  ad_api/api/sb/negative_keywords.py,sha256=ww3IRbawidDHAaYIkX5SsH2OZKJj4UnCylqqFeq3OoY,6918
43
44
  ad_api/api/sb/negative_product_targeting.py,sha256=QbK1EhhzmnNOzGtbkrAZ4HS5OqiLU3nZBmsl1scd2D0,5085
44
45
  ad_api/api/sb/product_targeting.py,sha256=o6aB3hIh9jKvi_uTXFi--1hpnPFuXzQ-U9N7VUP_Bz4,5362
45
- ad_api/api/sb/recommendations.py,sha256=Ck4DLAKLTqwodmQJfih9MUD1sujG6LDjRlSoefKmOC4,356
46
+ ad_api/api/sb/recommendations.py,sha256=_21L8tZPuArmJ30XyR1SKQHQH_yswvF0IMqwD9sLhgY,347
46
47
  ad_api/api/sb/reports.py,sha256=icw5DpRrqfj0idEo0NN1GPDpIWQun2h_c2Uwc7CpNUA,3801
47
48
  ad_api/api/sb/stores.py,sha256=sLdA6Lp37VR-ldu_sTUZIqc8MbMzysPhNOh05VaKBcA,4371
48
49
  ad_api/api/sb/targeting_recommendations.py,sha256=_7NxD5kC-Od11QOuLT03qpLVxEOIZgy-BtzniWK4CI8,2862
@@ -104,8 +105,8 @@ ad_api/base/exceptions.py,sha256=9D3M40ZIlLS0fA-aQh1BTWPOW-Nvf0tRhbA85jFnDJ4,438
104
105
  ad_api/base/helpers.py,sha256=naUkDLK466x_OBCPXxMlzRc2nPC6iQ6H_vyUji0MJJ0,2282
105
106
  ad_api/base/marketplaces.py,sha256=44lvCcluXNpqTprWQ80e3weSQmQbJoWL-WDSOWVbCyQ,4657
106
107
  ad_api/base/utils.py,sha256=_qnCBOvyJTLgaZjJzUWTi38GGLHkQszXELs79133Rb4,5618
107
- python_amazon_ad_api-1.1.1.dist-info/licenses/LICENSE,sha256=h2rpqlmmLy-4l1tN6KpWAFxx1JEMYeEFrMrZUbx_B_o,1105
108
- python_amazon_ad_api-1.1.1.dist-info/METADATA,sha256=1fucVhQrMK2AAFptVgk7GJhULzGQMGA4qpReJa7JQUw,20486
109
- python_amazon_ad_api-1.1.1.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
110
- python_amazon_ad_api-1.1.1.dist-info/top_level.txt,sha256=nN9twUos-8pkP514ZwpvRU9YL9L2XyQyHsMQFfudGTU,7
111
- python_amazon_ad_api-1.1.1.dist-info/RECORD,,
108
+ python_amazon_ad_api-1.1.3.dist-info/licenses/LICENSE,sha256=h2rpqlmmLy-4l1tN6KpWAFxx1JEMYeEFrMrZUbx_B_o,1105
109
+ python_amazon_ad_api-1.1.3.dist-info/METADATA,sha256=RB8aZ0VWmVNwW0nR_21GuKzyeNZQFCgFXSQgnKYIxdk,20486
110
+ python_amazon_ad_api-1.1.3.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
111
+ python_amazon_ad_api-1.1.3.dist-info/top_level.txt,sha256=nN9twUos-8pkP514ZwpvRU9YL9L2XyQyHsMQFfudGTU,7
112
+ python_amazon_ad_api-1.1.3.dist-info/RECORD,,