python-amazon-ad-api 1.2.9__tar.gz → 1.4.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.
Files changed (124) hide show
  1. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/PKG-INFO +4 -2
  2. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/README.md +2 -0
  3. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/__init__.py +3 -0
  4. python_amazon_ad_api-1.4.0/ad_api/api/account_budgets.py +53 -0
  5. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/attribution.py +51 -0
  6. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/brand_metrics.py +63 -7
  7. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/v1/__init__.py +2 -0
  8. python_amazon_ad_api-1.4.0/ad_api/api/v1/ad_extensions.py +125 -0
  9. python_amazon_ad_api-1.4.0/ad_api/version.py +1 -0
  10. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/python_amazon_ad_api.egg-info/PKG-INFO +4 -2
  11. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/python_amazon_ad_api.egg-info/SOURCES.txt +2 -0
  12. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/python_amazon_ad_api.egg-info/requires.txt +1 -1
  13. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/setup.cfg +1 -1
  14. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/setup.py +2 -2
  15. python_amazon_ad_api-1.2.9/ad_api/version.py +0 -1
  16. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/LICENSE +0 -0
  17. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/__init__.py +0 -0
  18. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/account.py +0 -0
  19. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/advertising_test_account.py +0 -0
  20. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/audiences.py +0 -0
  21. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/billing.py +0 -0
  22. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/creative_assets.py +0 -0
  23. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/eligibility.py +0 -0
  24. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/exports.py +0 -0
  25. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/history.py +0 -0
  26. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/insights.py +0 -0
  27. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/invoices.py +0 -0
  28. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/localization.py +0 -0
  29. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/manager_accounts.py +0 -0
  30. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/metadata.py +0 -0
  31. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/portfolios.py +0 -0
  32. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/portfolios_v3.py +0 -0
  33. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/profiles.py +0 -0
  34. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/recommendations.py +0 -0
  35. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/reports.py +0 -0
  36. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/__init__.py +0 -0
  37. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/ad_creatives_v4.py +0 -0
  38. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/ad_groups.py +0 -0
  39. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/ad_groups_v4.py +0 -0
  40. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/ads_v4.py +0 -0
  41. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/benchmarks.py +0 -0
  42. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/bid_recommendations.py +0 -0
  43. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/brands.py +0 -0
  44. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/budget_rules.py +0 -0
  45. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/campaigns.py +0 -0
  46. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/campaigns_v4.py +0 -0
  47. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/forecast.py +0 -0
  48. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/keywords.py +0 -0
  49. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/keywords_recommendations.py +0 -0
  50. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/landing_page_asins.py +0 -0
  51. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/media.py +0 -0
  52. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/migration.py +0 -0
  53. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/negative_keywords.py +0 -0
  54. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/negative_product_targeting.py +0 -0
  55. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/optimization_rules.py +0 -0
  56. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/product_targeting.py +0 -0
  57. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/recommendations.py +0 -0
  58. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/reports.py +0 -0
  59. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/stores.py +0 -0
  60. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/targeting_categories.py +0 -0
  61. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/targeting_recommendations.py +0 -0
  62. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sb/themes.py +0 -0
  63. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/__init__.py +0 -0
  64. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/ad_groups.py +0 -0
  65. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/bid_recommendations.py +0 -0
  66. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/brand_safety.py +0 -0
  67. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/budget_rules.py +0 -0
  68. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/campaigns.py +0 -0
  69. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/campaigns_budget_usage.py +0 -0
  70. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/creatives.py +0 -0
  71. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/forecast.py +0 -0
  72. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/negative_product_targeting.py +0 -0
  73. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/product_ads.py +0 -0
  74. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/product_targeting.py +0 -0
  75. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/recommendations.py +0 -0
  76. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/reports.py +0 -0
  77. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/snapshots.py +0 -0
  78. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sd/targeting_recommendations.py +0 -0
  79. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/__init__.py +0 -0
  80. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/ad_groups_v3.py +0 -0
  81. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/bid_recommendations_v3.py +0 -0
  82. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/budget_initial_recommendation.py +0 -0
  83. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/budget_recommendations.py +0 -0
  84. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/budget_rules.py +0 -0
  85. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/budget_rules_recommendations.py +0 -0
  86. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/campaign_consolidated_recommendations.py +0 -0
  87. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/campaign_negative_keywords_v3.py +0 -0
  88. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/campaign_negative_targets.py +0 -0
  89. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/campaigns_budget_usage.py +0 -0
  90. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/campaigns_v3.py +0 -0
  91. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/campaings_optimization.py +0 -0
  92. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/keywords_v3.py +0 -0
  93. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/negative_keywords_v3.py +0 -0
  94. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/negative_product_targeting_v3.py +0 -0
  95. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/product_ads_v3.py +0 -0
  96. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/product_recommendations.py +0 -0
  97. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/product_targeting_v3.py +0 -0
  98. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/ranked_keywords_recommendations.py +0 -0
  99. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/sp/schedule_based_bid_optimization.py +0 -0
  100. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/stores.py +0 -0
  101. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/stream.py +0 -0
  102. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/v1/ad_groups.py +0 -0
  103. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/v1/ads.py +0 -0
  104. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/v1/campaigns.py +0 -0
  105. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/v1/targets.py +0 -0
  106. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/api/validation_configurations.py +0 -0
  107. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/auth/__init__.py +0 -0
  108. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/auth/access_token_client.py +0 -0
  109. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/auth/access_token_response.py +0 -0
  110. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/auth/credentials.py +0 -0
  111. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/auth/exceptions.py +0 -0
  112. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/__init__.py +0 -0
  113. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/api_response.py +0 -0
  114. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/base_client.py +0 -0
  115. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/client.py +0 -0
  116. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/config.py +0 -0
  117. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/credential_provider.py +0 -0
  118. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/exceptions.py +0 -0
  119. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/helpers.py +0 -0
  120. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/marketplaces.py +0 -0
  121. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/ad_api/base/utils.py +0 -0
  122. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/pyproject.toml +0 -0
  123. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/python_amazon_ad_api.egg-info/dependency_links.txt +0 -0
  124. {python_amazon_ad_api-1.2.9 → python_amazon_ad_api-1.4.0}/python_amazon_ad_api.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-amazon-ad-api
3
- Version: 1.2.9
3
+ Version: 1.4.0
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
@@ -15,7 +15,7 @@ License-File: LICENSE
15
15
  Requires-Dist: requests<2.35.0,>=2.27.1
16
16
  Requires-Dist: six<1.18,>=1.16
17
17
  Requires-Dist: cachetools<7.3,>=5.0
18
- Requires-Dist: pycryptodome<4.2,>=3.13
18
+ Requires-Dist: pycryptodome<4.3,>=3.13
19
19
  Requires-Dist: pytz<2027.0,>=2021.3
20
20
  Requires-Dist: confuse<2.4,>=1.7
21
21
  Dynamic: author
@@ -266,6 +266,7 @@ curl \
266
266
  * [PortfoliosV3](https://python-amazon-ad-api.readthedocs.io/en/latest/api/portfoliosV3.html)
267
267
  * [Invoices](https://python-amazon-ad-api.readthedocs.io/en/latest/api/invoices.html)
268
268
  * [Billing](https://python-amazon-ad-api.readthedocs.io/en/latest/api/billing.html)
269
+ * [Account Budgets](https://python-amazon-ad-api.readthedocs.io/en/latest/api/account_budgets.html)
269
270
  * [Audiences](https://python-amazon-ad-api.readthedocs.io/en/latest/api/audiences.html)
270
271
  * [Change History](https://python-amazon-ad-api.readthedocs.io/en/latest/api/history.html)
271
272
  * [Creative Assets](https://python-amazon-ad-api.readthedocs.io/en/latest/api/creative_assets.html)
@@ -303,6 +304,7 @@ The v1 API lives under `/adsApi/v1/` and is **not** split by product: every call
303
304
  * [Ad Groups](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ad_groups.html#ad_api.api.v1.AdGroups.AdGroups.query_ad_groups)
304
305
  * [Ads](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ads.html#ad_api.api.v1.Ads.Ads.query_ads)
305
306
  * [Targets](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/targets.html#ad_api.api.v1.Targets.Targets.query_targets)
307
+ * [Ad Extensions](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ad_extensions.html#ad_api.api.v1.AdExtensions.AdExtensions.query_ad_extensions)
306
308
 
307
309
 
308
310
  ### [Modules Available Sponsored Products](https://python-amazon-ad-api.readthedocs.io/en/latest/sp.html)
@@ -238,6 +238,7 @@ curl \
238
238
  * [PortfoliosV3](https://python-amazon-ad-api.readthedocs.io/en/latest/api/portfoliosV3.html)
239
239
  * [Invoices](https://python-amazon-ad-api.readthedocs.io/en/latest/api/invoices.html)
240
240
  * [Billing](https://python-amazon-ad-api.readthedocs.io/en/latest/api/billing.html)
241
+ * [Account Budgets](https://python-amazon-ad-api.readthedocs.io/en/latest/api/account_budgets.html)
241
242
  * [Audiences](https://python-amazon-ad-api.readthedocs.io/en/latest/api/audiences.html)
242
243
  * [Change History](https://python-amazon-ad-api.readthedocs.io/en/latest/api/history.html)
243
244
  * [Creative Assets](https://python-amazon-ad-api.readthedocs.io/en/latest/api/creative_assets.html)
@@ -275,6 +276,7 @@ The v1 API lives under `/adsApi/v1/` and is **not** split by product: every call
275
276
  * [Ad Groups](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ad_groups.html#ad_api.api.v1.AdGroups.AdGroups.query_ad_groups)
276
277
  * [Ads](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ads.html#ad_api.api.v1.Ads.Ads.query_ads)
277
278
  * [Targets](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/targets.html#ad_api.api.v1.Targets.Targets.query_targets)
279
+ * [Ad Extensions](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ad_extensions.html#ad_api.api.v1.AdExtensions.AdExtensions.query_ad_extensions)
278
280
 
279
281
 
280
282
  ### [Modules Available Sponsored Products](https://python-amazon-ad-api.readthedocs.io/en/latest/sp.html)
@@ -3,6 +3,7 @@ from .profiles import Profiles
3
3
  from .manager_accounts import ManagerAccounts
4
4
  from .invoices import Invoices
5
5
  from .billing import Billing
6
+ from .account_budgets import AccountBudgets
6
7
  from .eligibility import Eligibility
7
8
  from .metadata import Metadata
8
9
  from .history import History
@@ -38,6 +39,7 @@ __all__ = [
38
39
  "ManagerAccounts",
39
40
  "Invoices",
40
41
  "Billing",
42
+ "AccountBudgets",
41
43
  "Eligibility",
42
44
  "Metadata",
43
45
  "History",
@@ -45,6 +47,7 @@ __all__ = [
45
47
  "Localization",
46
48
  "Audiences",
47
49
  "Portfolios",
50
+ "PortfoliosV3",
48
51
  "Insights",
49
52
  "Attribution",
50
53
  "BrandMetrics",
@@ -0,0 +1,53 @@
1
+ from ad_api.base import Client, sp_endpoint, ApiResponse, Utils
2
+
3
+
4
+ class AccountBudgets(Client):
5
+ """ """
6
+
7
+ @sp_endpoint('/accountBudgets/featureFlags', method='GET')
8
+ def get_feature_flags(self, **kwargs) -> ApiResponse:
9
+ r"""
10
+ Reports whether the account has opted out of automatic budget increases.
11
+
12
+ Returns
13
+ ApiResponse with a ``featureFlags`` object holding one member,
14
+ ``isOptedOutForAverageDailyBudgetIncrease``. At ``true`` the account
15
+ has opted out, and the service will not raise a campaign's daily
16
+ budget on its own; at ``false`` it may.
17
+
18
+ """
19
+ headers = {'Accept': 'application/vnd.accountBudgetFeatureFlags.v1+json'}
20
+ return self._request(kwargs.pop('path'), params=kwargs, headers=headers)
21
+
22
+ @sp_endpoint('/accountBudgets/featureFlags', method='POST')
23
+ def update_feature_flags(self, **kwargs) -> ApiResponse:
24
+ r"""
25
+ Changes whether the account opts out of automatic budget increases.
26
+
27
+ Request Body (required)
28
+
29
+ - ``featureFlags`` (object): required. A ``FeatureFlags`` object holding
30
+ ``isOptedOutForAverageDailyBudgetIncrease``. Set it to ``true`` to stop
31
+ the service raising daily budgets on its own, ``false`` to allow it.
32
+
33
+ .. warning::
34
+
35
+ This changes how the account is charged. With the flag at ``false``
36
+ the service may raise a campaign's daily budget without another call
37
+ from you, and spend follows the budget. Not exercised here: the
38
+ setting belongs to the account holder.
39
+
40
+ Returns
41
+ ApiResponse with ``code`` and ``details``, not with the flags read
42
+ back. ``code`` is ``OK``, ``ENTRY_NOT_FOUND`` or
43
+ ``INVALID_PARAMETER_VALUE``, so a ``200`` carrying something other
44
+ than ``OK`` means the change did not land. Read the flags again with
45
+ ``get_feature_flags`` to confirm.
46
+
47
+ """
48
+ headers = {
49
+ 'Accept': 'application/vnd.accountBudgetFeatureFlags.v1+json',
50
+ 'Content-Type': 'application/vnd.accountBudgetFeatureFlags.v1+json',
51
+ }
52
+ body = Utils.convert_body(kwargs.pop('body'), False)
53
+ return self._request(kwargs.pop('path'), data=body, params=kwargs, headers=headers)
@@ -9,6 +9,31 @@ class Attribution(Client):
9
9
  def get_advertisers(self, **kwargs) -> ApiResponse:
10
10
  r"""
11
11
  Gets a list of advertisers associated with an Amazon Attribution account.
12
+
13
+ Takes no query parameters. Send the request as is.
14
+
15
+ Returns:
16
+ ApiResponse. ``payload`` holds ``{"advertisers": [...]}`` with one
17
+ entry per advertiser:
18
+
19
+ - ``advertiserId`` (string): the identifier the other Attribution
20
+ routes accept as ``advertiserIds``.
21
+ - ``advertiserName`` (string): the display name.
22
+
23
+ Example:
24
+
25
+ .. code-block:: python
26
+
27
+ from ad_api.api import Attribution
28
+
29
+ attribution = Attribution(account="my_account")
30
+ attribution.get_advertisers().payload
31
+ # {'advertisers': [{'advertiserName': 'MY BRAND SPAIN',
32
+ # 'advertiserId': '586616515354498787'}]}
33
+
34
+ An account without Attribution access answers ``200`` with an empty
35
+ ``advertisers`` list, not a ``403``, so check the list itself.
36
+ ``ApiResponse`` does not carry the HTTP status code.
12
37
  """
13
38
  return self._request(fill_query_params(kwargs.pop("path")), params=kwargs)
14
39
 
@@ -16,6 +41,32 @@ class Attribution(Client):
16
41
  def get_publishers(self, **kwargs) -> ApiResponse:
17
42
  r"""
18
43
  Gets a list of all available publishers.
44
+
45
+ Takes no query parameters. Send the request as is. This is the call that
46
+ tells you which of the two tag routes each publisher belongs to.
47
+
48
+ Returns:
49
+ ApiResponse. ``payload`` holds ``{"publishers": [...]}`` with one
50
+ entry per publisher:
51
+
52
+ - ``id`` (string): the value to pass as ``publisherIds``.
53
+ - ``name`` (string): the display name, such as ``Google Ads``.
54
+ - ``macroEnabled`` (boolean): ``True`` when the publisher expands
55
+ tracking macros in its click-through URLs, and therefore belongs
56
+ to :meth:`get_macro_tag`. ``False`` means it needs fixed values
57
+ and belongs to :meth:`get_non_macro_template_tag`.
58
+
59
+ Example:
60
+
61
+ .. code-block:: python
62
+
63
+ publishers = Attribution(account="my_account").get_publishers().payload["publishers"]
64
+ macro = [p["id"] for p in publishers if p["macroEnabled"]]
65
+ plain = [p["id"] for p in publishers if not p["macroEnabled"]]
66
+
67
+ Google Ads, Facebook Ads, Microsoft Ads and Pinterest Ads report
68
+ ``macroEnabled`` true. The rest, among them Snapchat, Twitter, LinkedIn
69
+ and TikTok, report false.
19
70
  """
20
71
  return self._request(fill_query_params(kwargs.pop("path")), params=kwargs)
21
72
 
@@ -8,22 +8,60 @@ class BrandMetrics(Client):
8
8
 
9
9
  @sp_endpoint('/insights/brandMetrics/report', method='POST')
10
10
  def post_report(self, **kwargs) -> ApiResponse:
11
- r"""Requests a Sponsored Brands report.
11
+ r"""Requests a Brand Metrics report.
12
12
 
13
- Generates the Brand Metrics report in CSV or JSON format. Customize the report by passing a specific categoryNodeTreeName, categoryNodePath, brandName, reportStartDate, reportEndDate, lookbackPeriod, format or a list of metrics from the available metrics in the metrics field. If an empty request body is passed, report for the latest available report date in JSON format will get generated with all the available brands and metrics for an advertiser. The report may or may not contain the Brand Metrics data for one or more brands depending on data availability.
13
+ Asks the service to generate the report; the answer is a handle, not the
14
+ data. It carries a ``reportId``, a ``status`` and an empty
15
+ ``location``, and the report is produced asynchronously. Pass the
16
+ ``reportId`` to :meth:`get_report` until ``status`` reads
17
+ ``SUCCESSFUL``, then download ``location``.
18
+
19
+ Generates the Brand Metrics report in CSV or JSON format. Customize the report by passing a specific categoryTreeName, categoryPath, brandName, reportStartDate, reportEndDate, lookBackPeriod, format or a list of metrics from the available metrics in the metrics field. If an empty request body is passed, report for the latest available report date in JSON format will get generated with all the available brands and metrics for an advertiser. The report may or may not contain the Brand Metrics data for one or more brands depending on data availability.
20
+
21
+ Every field is optional. An empty ``body`` generates the latest
22
+ available report in JSON with every brand and metric on the account.
14
23
 
15
24
  Request body
16
- | **categoryNodeTreeName** (string): [optional] The node at the top of a browse tree. It is the start node of a tree. example: us-home
17
- | **categoryNodePath** (string): [optional] The hierarchical path that leads to a node starting with the root node. If no Category Node Name is passed, then all data available for all brands belonging to the entity are retrieved. example: List [ "Categories", "Snack Food", "Granola & Snack Bars" ]]
25
+ | **categoryTreeName** (string): [optional] The node at the top of a browse tree. It is the start node of a tree. example: us-home
26
+ | **categoryPath** (array of arrays): [optional] The hierarchical path that leads to a node starting with the root node, as a list of paths where each path is a list of levels. If no category path is passed, then all data available for all brands belonging to the entity are retrieved. example: [ ["Categories", "Granola & Snack Bars", "Snack Food"] ]
27
+
18
28
  | **brandName** (string): [optional] Brand Name. If no Brand Name is passed, then all data available for all brands belonging to the entity are retrieved. example: Mattress Mogul
19
29
  | **reportStartDate** (string($date)): [optional] Retrieves metrics with metricsComputationDate between reportStartDate and reportEndDate (inclusive). The date will be in the Coordinated Universal Time (UTC) timezone in YYYY-MM-DD format. If no date is passed in reportStartDate, all available metrics with metricsComputationDate till the reportEndDate will be provided. If no date is passed for either reportStartDate or reportEndDate, the metrics with the most receont metricsComputationDate will be returned. example: 2021-01-01
20
- | **lookBackPeriod** (string) [optional] Currently supported values: "1w" (one week), "1m" (one month) and "1cm" (one calendar month). This defines the period of time used to determine the number of shoppers in the metrics computation [ 1m, 1w, 1cm ]. default: 1w
30
+ | **lookBackPeriod** (string) [optional] Currently supported values: "1W" (one week), "1M" (one month) and "1CM" (one calendar month), which is the enum the v1 contract declares; the v1.1 contract declares the lower case forms and the service accepted both. This defines the period of time used to determine the number of shoppers in the metrics computation. default: 1w
21
31
  | **format** (string) [optional] Format of the report. [ JSON, CSV ]. default: JSON
22
32
  | **metrics** (list) [optional] Specify an array of string of metrics field names to include in the report. If no metric field names are specified, all metrics are returned.
23
33
  | **reportEndDate** (string($date)) [optional] Retrieves metrics with metricsComputationDate between reportStartDate and reportEndDate (inclusive). The date will be in the Coordinated Universal Time (UTC) timezone in YYYY-MM-DD format. If no date is passed in reportEndDate, all available metrics with metricsComputationDate from the reportStartDate will be provided. If no date is passed for either reportStartDate or reportEndDate, the metrics with the most receont metricsComputationDate will be returned. example: 2021-01-30
24
34
 
35
+ The contract names the two category fields ``categoryTreeName`` and
36
+ ``categoryPath``, while the answers come back carrying
37
+ ``categoryNodeTreeName`` and ``categoryNodeName``. Neither spelling
38
+ filters: both were sent with different values, and a tree name that does
39
+ not exist (``zz-no-existe-zz``) was answered with the account's full set
40
+ exactly like a real one. Send the contract names, but do not expect them
41
+ to narrow the report -- filter on ``brandName`` and the date range
42
+ instead, which are the fields the service was seen to honour.
43
+
25
44
  Returns:
26
- ApiResponse
45
+ ApiResponse. ``payload`` holds:
46
+
47
+ - ``reportId`` (string): the handle for :meth:`get_report`.
48
+ - ``status`` (string): ``IN_PROGRESS`` on a fresh request.
49
+ - ``statusDetails`` (string): a sentence describing that status.
50
+ - ``expiration`` (integer): how long the result stays available.
51
+ - ``format`` (string): echoes the requested format.
52
+ - ``location`` (string): empty until the report is ready.
53
+
54
+ Example:
55
+
56
+ .. code-block:: python
57
+
58
+ from ad_api.api import BrandMetrics
59
+
60
+ bm = BrandMetrics(account="my_account")
61
+ bm.post_report(body={"format": "JSON", "lookBackPeriod": "1w"}).payload
62
+ # {'reportId': '8d3e7143-...', 'status': 'IN_PROGRESS',
63
+ # 'statusDetails': 'Generation of the report is in progress!',
64
+ # 'expiration': 300000, 'format': 'JSON', 'location': ''}
27
65
 
28
66
  """
29
67
  return self._request(fill_query_params(kwargs.pop('path')), data=Utils.convert_body(kwargs.pop('body'), False), params=kwargs)
@@ -32,11 +70,29 @@ class BrandMetrics(Client):
32
70
  def get_report(self, reportId, **kwargs) -> ApiResponse:
33
71
  r"""Gets a previously requested report specified by identifier.
34
72
 
73
+ This is the polling call. A report is generated asynchronously, so call
74
+ this with the ``reportId`` that :meth:`post_report` returned until
75
+ ``status`` reads ``SUCCESSFUL``; only then does ``location`` carry
76
+ a signed S3 address that can be downloaded.
77
+
35
78
  Keyword Args
36
79
  | path **reportId** (string): [required] The report Id to be fetched.
37
80
 
38
81
  Returns:
39
- ApiResponse
82
+ ApiResponse. ``payload`` holds:
83
+
84
+ - ``status`` (string): ``IN_PROGRESS``, ``SUCCESSFUL`` or a
85
+ failure status.
86
+ - ``statusDetails`` (string): the sentence behind that status.
87
+ - ``location`` (string): the signed URL, empty until success.
88
+ - ``format`` (string): the format the report was generated in.
89
+ - ``expiration`` (integer): how long the result stays available.
90
+ - ``brandsInfo`` (array): the brands the report covers, each with
91
+ ``id`` and ``name``. Absent while the report is still running.
92
+
93
+ An unknown identifier is not a ``404``: the service answers ``400``
94
+ with ``NoDataFoundException`` and a message naming the id, which means
95
+ the route ran and looked it up.
40
96
  """
41
97
  return self._request(fill_query_params(kwargs.pop('path'), reportId), params=kwargs)
42
98
 
@@ -2,10 +2,12 @@ from .campaigns import Campaigns
2
2
  from .ad_groups import AdGroups
3
3
  from .ads import Ads
4
4
  from .targets import Targets
5
+ from .ad_extensions import AdExtensions
5
6
 
6
7
  __all__ = [
7
8
  "Campaigns",
8
9
  "AdGroups",
9
10
  "Ads",
10
11
  "Targets",
12
+ "AdExtensions",
11
13
  ]
@@ -0,0 +1,125 @@
1
+ from ad_api.base import Client, sp_endpoint, ApiResponse, Utils
2
+
3
+
4
+ class AdExtensions(Client):
5
+ r"""
6
+ AdExtensions(account='default', marketplace: Marketplaces = Marketplaces.EU, credentials=None, debug=False)
7
+
8
+ Amazon Ads API v1 - unified AdExtensions endpoints
9
+
10
+ An ad extension adds delivery detail to an existing Sponsored Products ad
11
+ rather than creating a new one. The contract declares exactly two types:
12
+
13
+ - ``PROMPTS`` -- a prompt-style text extension.
14
+ - ``VIDEO`` -- a video extension.
15
+
16
+ There is no delete route. An extension is created, queried and updated; the
17
+ only thing ``update`` changes is ``state``, so ending one means pausing or
18
+ archiving it. Editing its content means creating a new extension and
19
+ archiving the old one.
20
+
21
+ Like every v1 resource, the product is chosen in the body through
22
+ ``adProductFilter`` / ``adProduct``, never in the path. For this contract
23
+ the enum is a single value, ``SPONSORED_PRODUCTS``.
24
+ """
25
+
26
+ @sp_endpoint('/adsApi/v1/query/adExtensions', method='POST')
27
+ def query_ad_extensions(self, **kwargs) -> ApiResponse:
28
+ r"""
29
+ query_ad_extensions(body: dict) -> ApiResponse
30
+
31
+ Amazon Ads API v1 - Query AdExtensions (operationId: SPQueryAdExtension)
32
+
33
+ Request Body
34
+ | **adProductFilter** (dict) [optional here, required by the service in practice]
35
+ | **include** (list<AdProduct>) : Enum [ SPONSORED_PRODUCTS ]
36
+ | **adIdFilter** (dict) [optional]
37
+ | **include** (list<string>) : 1..300 ad identifiers
38
+ | **adGroupIdFilter** (dict) [optional]
39
+ | **include** (list<string>) : ad group identifiers
40
+ | **adExtensionIdFilter** (dict) [optional]
41
+ | **include** (list<string>) : extension identifiers
42
+ | **adExtensionStatusFilter** (dict) [optional]
43
+ | **include** (list<AdExtensionStatus>)
44
+ | **adExtensionTypeFilter** (dict) [optional]
45
+ | **include** (list<AdExtensionType>) : Enum [ PROMPTS, VIDEO ], exactly one value
46
+ | **stateFilter** (dict) [optional]
47
+ | **include** (list<State>) : Enum [ ENABLED, PAUSED, ARCHIVED ], 1..3 values
48
+ | **maxResults** (int) [optional] Maximum number of records in the response
49
+ | **nextToken** (string) [optional] Token to navigate to the next page
50
+
51
+ Every filter object is shaped ``{"include": [...]}``, and ``include`` is
52
+ required inside each one. An empty ``{}`` body is not the same as no
53
+ filter: send the body you mean.
54
+
55
+ Returns
56
+ ApiResponse
57
+ """
58
+ headers = {"Accept": "application/json", "Content-Type": "application/json"}
59
+ return self._request(
60
+ kwargs.pop('path'),
61
+ data=Utils.convert_body(kwargs.pop('body'), False),
62
+ params=kwargs,
63
+ headers=headers,
64
+ )
65
+
66
+ @sp_endpoint('/adsApi/v1/create/adExtensions', method='POST')
67
+ def create_ad_extensions(self, **kwargs) -> ApiResponse:
68
+ r"""
69
+ create_ad_extensions(body: dict) -> ApiResponse
70
+
71
+ Amazon Ads API v1 - Create AdExtensions (operationId: SPCreateAdExtension)
72
+
73
+ Request Body [Required]
74
+ | **adExtensions** (list, 1..50) [required]
75
+
76
+ Each element:
77
+ | **adExtensionSettings** (SPCreateAdExtensionSettings) [required]
78
+ | **adExtensionType** (string) [required] Enum [ PROMPTS, VIDEO ]
79
+ | **adProduct** (string) [required] Enum [ SPONSORED_PRODUCTS ]
80
+ | **marketplaceScope** (string) [required] Enum [ SINGLE_MARKETPLACE ]
81
+ | **marketplaces** (list<string>) [required] marketplaces the extension applies to
82
+ | **state** (string) [required] Enum [ ENABLED, PAUSED ]
83
+ | **adExtensionStatus** (SPAdExtensionStatus) [optional]
84
+ | **adGroupId** (string) [optional] ad group the extension belongs to
85
+ | **adId** (string) [optional] ad the extension belongs to
86
+
87
+ Returns
88
+ ApiResponse
89
+ """
90
+ headers = {"Accept": "application/json", "Content-Type": "application/json"}
91
+ return self._request(
92
+ kwargs.pop('path'),
93
+ data=Utils.convert_body(kwargs.pop('body'), False),
94
+ params=kwargs,
95
+ headers=headers,
96
+ )
97
+
98
+ @sp_endpoint('/adsApi/v1/update/adExtensions', method='POST')
99
+ def update_ad_extensions(self, **kwargs) -> ApiResponse:
100
+ r"""
101
+ update_ad_extensions(body: dict) -> ApiResponse
102
+
103
+ Amazon Ads API v1 - Update AdExtensions (operationId: SPUpdateAdExtension)
104
+
105
+ The contract accepts only an identifier and a state here. There is no
106
+ field to change the extension's own content, so this route switches an
107
+ extension on, off or out of the way; it does not rewrite it.
108
+
109
+ Request Body [Required]
110
+ | **adExtensions** (list, 1..50) [required]
111
+
112
+ Each element:
113
+ | **adExtensionId** (string) [required] extension to update
114
+ | **state** (string) [optional] Enum [ ENABLED, PAUSED, ARCHIVED ]
115
+
116
+ Returns
117
+ ApiResponse
118
+ """
119
+ headers = {"Accept": "application/json", "Content-Type": "application/json"}
120
+ return self._request(
121
+ kwargs.pop('path'),
122
+ data=Utils.convert_body(kwargs.pop('body'), False),
123
+ params=kwargs,
124
+ headers=headers,
125
+ )
@@ -0,0 +1 @@
1
+ __version__ = "1.4.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-amazon-ad-api
3
- Version: 1.2.9
3
+ Version: 1.4.0
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
@@ -15,7 +15,7 @@ License-File: LICENSE
15
15
  Requires-Dist: requests<2.35.0,>=2.27.1
16
16
  Requires-Dist: six<1.18,>=1.16
17
17
  Requires-Dist: cachetools<7.3,>=5.0
18
- Requires-Dist: pycryptodome<4.2,>=3.13
18
+ Requires-Dist: pycryptodome<4.3,>=3.13
19
19
  Requires-Dist: pytz<2027.0,>=2021.3
20
20
  Requires-Dist: confuse<2.4,>=1.7
21
21
  Dynamic: author
@@ -266,6 +266,7 @@ curl \
266
266
  * [PortfoliosV3](https://python-amazon-ad-api.readthedocs.io/en/latest/api/portfoliosV3.html)
267
267
  * [Invoices](https://python-amazon-ad-api.readthedocs.io/en/latest/api/invoices.html)
268
268
  * [Billing](https://python-amazon-ad-api.readthedocs.io/en/latest/api/billing.html)
269
+ * [Account Budgets](https://python-amazon-ad-api.readthedocs.io/en/latest/api/account_budgets.html)
269
270
  * [Audiences](https://python-amazon-ad-api.readthedocs.io/en/latest/api/audiences.html)
270
271
  * [Change History](https://python-amazon-ad-api.readthedocs.io/en/latest/api/history.html)
271
272
  * [Creative Assets](https://python-amazon-ad-api.readthedocs.io/en/latest/api/creative_assets.html)
@@ -303,6 +304,7 @@ The v1 API lives under `/adsApi/v1/` and is **not** split by product: every call
303
304
  * [Ad Groups](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ad_groups.html#ad_api.api.v1.AdGroups.AdGroups.query_ad_groups)
304
305
  * [Ads](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ads.html#ad_api.api.v1.Ads.Ads.query_ads)
305
306
  * [Targets](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/targets.html#ad_api.api.v1.Targets.Targets.query_targets)
307
+ * [Ad Extensions](https://python-amazon-ad-api.readthedocs.io/en/latest/v1/ad_extensions.html#ad_api.api.v1.AdExtensions.AdExtensions.query_ad_extensions)
306
308
 
307
309
 
308
310
  ### [Modules Available Sponsored Products](https://python-amazon-ad-api.readthedocs.io/en/latest/sp.html)
@@ -7,6 +7,7 @@ ad_api/__init__.py
7
7
  ad_api/version.py
8
8
  ad_api/api/__init__.py
9
9
  ad_api/api/account.py
10
+ ad_api/api/account_budgets.py
10
11
  ad_api/api/advertising_test_account.py
11
12
  ad_api/api/attribution.py
12
13
  ad_api/api/audiences.py
@@ -94,6 +95,7 @@ ad_api/api/sp/product_targeting_v3.py
94
95
  ad_api/api/sp/ranked_keywords_recommendations.py
95
96
  ad_api/api/sp/schedule_based_bid_optimization.py
96
97
  ad_api/api/v1/__init__.py
98
+ ad_api/api/v1/ad_extensions.py
97
99
  ad_api/api/v1/ad_groups.py
98
100
  ad_api/api/v1/ads.py
99
101
  ad_api/api/v1/campaigns.py
@@ -1,6 +1,6 @@
1
1
  requests<2.35.0,>=2.27.1
2
2
  six<1.18,>=1.16
3
3
  cachetools<7.3,>=5.0
4
- pycryptodome<4.2,>=3.13
4
+ pycryptodome<4.3,>=3.13
5
5
  pytz<2027.0,>=2021.3
6
6
  confuse<2.4,>=1.7
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = python-amazon-ad-api
3
- version = 1.2.9
3
+ version = 1.4.0
4
4
  author = Daniel Alvaro
5
5
  author_email = denisneuf@hotmail.com
6
6
  description = Python wrapper for the Amazon Advertising API
@@ -2,12 +2,12 @@ from setuptools import setup
2
2
 
3
3
  setup(
4
4
  name='python-amazon-ad-api',
5
- version='1.2.9',
5
+ version='1.4.0',
6
6
  install_requires=[
7
7
  "requests>=2.27.1,<2.35.0",
8
8
  "six>=1.16,<1.18",
9
9
  "cachetools>=5.0,<7.3",
10
- "pycryptodome>=3.13,<4.2",
10
+ "pycryptodome>=3.13,<4.3",
11
11
  "pytz>=2021.3,<2027.0",
12
12
  "confuse>=1.7,<2.4",
13
13
  ],
@@ -1 +0,0 @@
1
- __version__ = "1.2.9"