python-amazon-sp-api 1.9.34__py3-none-any.whl → 2.0.7__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.
Files changed (162) hide show
  1. {python_amazon_sp_api-1.9.34.dist-info → python_amazon_sp_api-2.0.7.dist-info}/METADATA +44 -20
  2. python_amazon_sp_api-2.0.7.dist-info/RECORD +251 -0
  3. {python_amazon_sp_api-1.9.34.dist-info → python_amazon_sp_api-2.0.7.dist-info}/top_level.txt +0 -1
  4. sp_api/__version__.py +1 -1
  5. sp_api/api/__init__.py +5 -2
  6. sp_api/api/application_integrations/application_integrations.py +2 -2
  7. sp_api/api/catalog/catalog.py +3 -4
  8. sp_api/api/catalog_items/catalog_items.py +3 -6
  9. sp_api/api/customer_feedback/customer_feedback.py +110 -0
  10. sp_api/api/data_kiosk/data_kiosk.py +5 -6
  11. sp_api/api/easy_ship/easy_ship.py +5 -5
  12. sp_api/api/external_fulfillment/external_fulfillment.py +706 -0
  13. sp_api/api/feeds/feeds.py +11 -8
  14. sp_api/api/fulfillment_inbound/fulfillment_inbound.py +35 -2
  15. sp_api/api/inventories/inventories.py +2 -7
  16. sp_api/api/listings_items/listings_items.py +3 -24
  17. sp_api/api/messaging/messaging.py +42 -0
  18. sp_api/api/orders/orders.py +7 -0
  19. sp_api/api/product_fees/product_fees.py +31 -74
  20. sp_api/api/products/products.py +3 -1
  21. sp_api/api/products/products_definitions.py +11 -169
  22. sp_api/api/reports/reports.py +61 -96
  23. sp_api/api/sales/sales.py +2 -2
  24. sp_api/asyncio/api/__init__.py +164 -0
  25. sp_api/asyncio/api/amazon_warehousing_and_distribu/__init__.py +9 -0
  26. sp_api/asyncio/api/amazon_warehousing_and_distribu/amazon_warehousing_and_distribu.py +130 -0
  27. sp_api/asyncio/api/aplus_content/__init__.py +5 -0
  28. sp_api/asyncio/api/aplus_content/aplus_content.py +330 -0
  29. sp_api/asyncio/api/application_integrations/__init__.py +5 -0
  30. sp_api/asyncio/api/application_integrations/application_integrations.py +119 -0
  31. sp_api/asyncio/api/application_management/__init__.py +5 -0
  32. sp_api/asyncio/api/application_management/application_management.py +36 -0
  33. sp_api/asyncio/api/authorization/__init__.py +5 -0
  34. sp_api/asyncio/api/authorization/authorization.py +54 -0
  35. sp_api/asyncio/api/catalog/__init__.py +5 -0
  36. sp_api/asyncio/api/catalog/catalog.py +111 -0
  37. sp_api/asyncio/api/catalog_items/__init__.py +6 -0
  38. sp_api/asyncio/api/catalog_items/catalog_items.py +93 -0
  39. sp_api/asyncio/api/clients/__init__.py +1 -0
  40. sp_api/asyncio/api/customer_feedback/__init__.py +5 -0
  41. sp_api/asyncio/api/customer_feedback/customer_feedback.py +111 -0
  42. sp_api/asyncio/api/data_kiosk/__init__.py +5 -0
  43. sp_api/asyncio/api/data_kiosk/data_kiosk.py +236 -0
  44. sp_api/asyncio/api/easy_ship/__init__.py +5 -0
  45. sp_api/asyncio/api/easy_ship/easy_ship.py +191 -0
  46. sp_api/asyncio/api/external_fulfillment/__init__.py +5 -0
  47. sp_api/asyncio/api/external_fulfillment/external_fulfillment.py +706 -0
  48. sp_api/asyncio/api/fba_inbound_eligibility/__init__.py +5 -0
  49. sp_api/asyncio/api/fba_inbound_eligibility/fba_inbound_eligibility.py +96 -0
  50. sp_api/asyncio/api/fba_small_and_light/__init__.py +5 -0
  51. sp_api/asyncio/api/fba_small_and_light/fba_small_and_light.py +213 -0
  52. sp_api/asyncio/api/feeds/feeds.py +260 -0
  53. sp_api/asyncio/api/finances/finances.py +100 -0
  54. sp_api/asyncio/api/fulfillment_inbound/fulfillment_inbound.py +1798 -0
  55. sp_api/asyncio/api/fulfillment_outbound/fulfillment_outbound.py +736 -0
  56. sp_api/asyncio/api/inventories/inventories.py +74 -0
  57. sp_api/asyncio/api/listings_items/listings_items.py +170 -0
  58. sp_api/asyncio/api/listings_restrictions/listings_restrictions.py +36 -0
  59. sp_api/asyncio/api/merchant_fulfillment/__init__.py +0 -0
  60. sp_api/asyncio/api/merchant_fulfillment/merchant_fulfillment.py +384 -0
  61. sp_api/asyncio/api/messaging/__init__.py +0 -0
  62. sp_api/asyncio/api/messaging/messaging.py +511 -0
  63. sp_api/asyncio/api/models/__init__.py +4 -0
  64. sp_api/asyncio/api/notifications/__init__.py +0 -0
  65. sp_api/asyncio/api/notifications/notifications.py +295 -0
  66. sp_api/asyncio/api/orders/__init__.py +0 -0
  67. sp_api/asyncio/api/orders/orders.py +362 -0
  68. sp_api/asyncio/api/overrides/__init__.py +1 -0
  69. sp_api/asyncio/api/product_fees/__init__.py +0 -0
  70. sp_api/asyncio/api/product_fees/product_fees.py +194 -0
  71. sp_api/asyncio/api/product_type_definitions/__init__.py +0 -0
  72. sp_api/asyncio/api/product_type_definitions/product_type_definitions.py +75 -0
  73. sp_api/asyncio/api/products/__init__.py +0 -0
  74. sp_api/asyncio/api/products/products.py +405 -0
  75. sp_api/asyncio/api/products/products_definitions.py +11 -0
  76. sp_api/asyncio/api/replenishment/__init__.py +0 -0
  77. sp_api/asyncio/api/replenishment/replenishment.py +121 -0
  78. sp_api/asyncio/api/reports/__init__.py +0 -0
  79. sp_api/asyncio/api/reports/reports.py +439 -0
  80. sp_api/asyncio/api/sales/__init__.py +0 -0
  81. sp_api/asyncio/api/sales/sales.py +93 -0
  82. sp_api/asyncio/api/sellers/__init__.py +0 -0
  83. sp_api/asyncio/api/sellers/sellers.py +70 -0
  84. sp_api/asyncio/api/services/__init__.py +0 -0
  85. sp_api/asyncio/api/services/services.py +218 -0
  86. sp_api/asyncio/api/shipping/__init__.py +0 -0
  87. sp_api/asyncio/api/shipping/shipping.py +459 -0
  88. sp_api/asyncio/api/shipping/shippingV2.py +651 -0
  89. sp_api/asyncio/api/solicitations/__init__.py +0 -0
  90. sp_api/asyncio/api/solicitations/solicitations.py +78 -0
  91. sp_api/asyncio/api/supply_sources/__init__.py +0 -0
  92. sp_api/asyncio/api/supply_sources/supply_sources.py +138 -0
  93. sp_api/asyncio/api/tokens/__init__.py +0 -0
  94. sp_api/asyncio/api/tokens/tokens.py +65 -0
  95. sp_api/asyncio/api/upload/__init__.py +0 -0
  96. sp_api/asyncio/api/upload/upload.py +18 -0
  97. sp_api/asyncio/api/vendor_direct_fulfillment_inventory/__init__.py +0 -0
  98. sp_api/asyncio/api/vendor_direct_fulfillment_inventory/vendor_direct_fulfillment_inventory.py +64 -0
  99. sp_api/asyncio/api/vendor_direct_fulfillment_orders/__init__.py +0 -0
  100. sp_api/asyncio/api/vendor_direct_fulfillment_orders/vendor_direct_fulfillment_orders.py +196 -0
  101. sp_api/asyncio/api/vendor_direct_fulfillment_payments/__init__.py +0 -0
  102. sp_api/asyncio/api/vendor_direct_fulfillment_payments/vendor_direct_fulfillment_payments.py +254 -0
  103. sp_api/asyncio/api/vendor_direct_fulfillment_shipping/__init__.py +0 -0
  104. sp_api/asyncio/api/vendor_direct_fulfillment_shipping/vendor_direct_fulfillment_shipping.py +627 -0
  105. sp_api/asyncio/api/vendor_direct_fulfillment_transactions/__init__.py +0 -0
  106. sp_api/asyncio/api/vendor_direct_fulfillment_transactions/vendor_direct_fulfillment_transactions.py +43 -0
  107. sp_api/asyncio/api/vendor_invoices/__init__.py +0 -0
  108. sp_api/asyncio/api/vendor_invoices/vendor_invoices.py +295 -0
  109. sp_api/asyncio/api/vendor_orders/__init__.py +0 -0
  110. sp_api/asyncio/api/vendor_orders/vendor_orders.py +210 -0
  111. sp_api/asyncio/api/vendor_shipments/__init__.py +0 -0
  112. sp_api/asyncio/api/vendor_shipments/vendor_shipments.py +118 -0
  113. sp_api/asyncio/api/vendor_transaction_status/__init__.py +0 -0
  114. sp_api/asyncio/api/vendor_transaction_status/vendor_transaction_status.py +41 -0
  115. sp_api/asyncio/auth/__init__.py +12 -0
  116. sp_api/asyncio/auth/access_token_client.py +145 -0
  117. sp_api/asyncio/auth/exceptions.py +5 -0
  118. sp_api/asyncio/base/__init__.py +53 -0
  119. sp_api/asyncio/base/_transport_httpx.py +50 -0
  120. sp_api/asyncio/base/base_client.py +8 -0
  121. sp_api/asyncio/base/client.py +169 -0
  122. sp_api/asyncio/util/__init__.py +29 -0
  123. sp_api/asyncio/util/key_maker.py +5 -0
  124. sp_api/asyncio/util/load_all_pages.py +55 -0
  125. sp_api/asyncio/util/load_date_bound.py +53 -0
  126. sp_api/asyncio/util/retry.py +88 -0
  127. sp_api/auth/_core.py +39 -0
  128. sp_api/auth/access_token_client.py +18 -29
  129. sp_api/base/ApiResponse.py +2 -2
  130. sp_api/base/_core.py +110 -0
  131. sp_api/base/_transport_httpx.py +39 -0
  132. sp_api/base/client.py +40 -63
  133. sp_api/base/helpers.py +1 -1
  134. sp_api/base/reportTypes.py +3 -2
  135. sp_api/util/__init__.py +36 -0
  136. sp_api/util/params.py +57 -0
  137. sp_api/util/product_fees.py +40 -0
  138. sp_api/util/products_definitions.py +169 -0
  139. sp_api/util/report_document.py +154 -0
  140. python_amazon_sp_api-1.9.34.dist-info/RECORD +0 -148
  141. tests/api/finances/test_finances.py +0 -19
  142. tests/api/notifications/test_notifications.py +0 -26
  143. tests/api/orders/test_orders.py +0 -122
  144. tests/api/product_fees/product_fees.py +0 -49
  145. tests/api/reports/test_reports.py +0 -127
  146. tests/client/test_auth.py +0 -59
  147. tests/client/test_base.py +0 -163
  148. tests/client/test_credential_provider.py +0 -45
  149. tests/client/test_helpers.py +0 -142
  150. {python_amazon_sp_api-1.9.34.data → python_amazon_sp_api-2.0.7.data}/scripts/make_endpoint +0 -0
  151. {python_amazon_sp_api-1.9.34.dist-info → python_amazon_sp_api-2.0.7.dist-info}/WHEEL +0 -0
  152. {python_amazon_sp_api-1.9.34.dist-info → python_amazon_sp_api-2.0.7.dist-info}/licenses/LICENSE +0 -0
  153. {tests → sp_api/api/customer_feedback}/__init__.py +0 -0
  154. {tests/api → sp_api/api/external_fulfillment}/__init__.py +0 -0
  155. {tests/api/finances → sp_api/asyncio}/__init__.py +0 -0
  156. {tests/api/notifications → sp_api/asyncio/api/feeds}/__init__.py +0 -0
  157. {tests/api/orders → sp_api/asyncio/api/finances}/__init__.py +0 -0
  158. {tests/api/product_fees → sp_api/asyncio/api/fulfillment_inbound}/__init__.py +0 -0
  159. {tests/api/reports → sp_api/asyncio/api/fulfillment_outbound}/__init__.py +0 -0
  160. {tests/api/sellers → sp_api/asyncio/api/inventories}/__init__.py +0 -0
  161. {tests/client → sp_api/asyncio/api/listings_items}/__init__.py +0 -0
  162. /tests/api/sellers/test_sellers.py → /sp_api/asyncio/api/listings_restrictions/__init__.py +0 -0
sp_api/api/feeds/feeds.py CHANGED
@@ -1,8 +1,9 @@
1
1
  import zlib
2
2
 
3
- import requests
3
+ import httpx
4
4
 
5
5
  from sp_api.base import Client, sp_endpoint, fill_query_params, ApiResponse
6
+ from sp_api.util import should_add_marketplace
6
7
 
7
8
 
8
9
  class Feeds(Client):
@@ -34,7 +35,7 @@ class Feeds(Client):
34
35
  ApiResponse:
35
36
  """
36
37
 
37
- add_marketplace = not "nextToken" in kwargs
38
+ add_marketplace = should_add_marketplace(kwargs, "nextToken")
38
39
  return self._request(
39
40
  kwargs.pop("path"), params=kwargs, add_marketplace=add_marketplace
40
41
  )
@@ -185,11 +186,12 @@ class Feeds(Client):
185
186
  upload_data = upload_data.encode("iso-8859-1")
186
187
  except AttributeError:
187
188
  pass
188
- upload = requests.put(
189
- response.payload.get("url"),
190
- data=upload_data,
191
- headers={"Content-Type": content_type},
192
- )
189
+ with httpx.Client() as client:
190
+ upload = client.put(
191
+ response.payload.get("url"),
192
+ content=upload_data,
193
+ headers={"Content-Type": content_type},
194
+ )
193
195
  if 200 <= upload.status_code < 300:
194
196
  return response
195
197
  from sp_api.base.exceptions import SellingApiException
@@ -240,7 +242,8 @@ class Feeds(Client):
240
242
  add_marketplace=False,
241
243
  )
242
244
  url = response.payload.get("url")
243
- doc_response = requests.get(url)
245
+ with httpx.Client() as client:
246
+ doc_response = client.get(url)
244
247
 
245
248
  encoding = (
246
249
  doc_response.encoding
@@ -4,6 +4,7 @@ from sp_api.base import Client, Marketplaces, ApiResponse
4
4
  from sp_api.base import sp_endpoint, fill_query_params
5
5
 
6
6
  import urllib.parse
7
+ from sp_api.util import ensure_csv
7
8
 
8
9
 
9
10
  class FulfillmentInboundVersion(str, enum.Enum):
@@ -197,6 +198,39 @@ class FulfillmentInbound(Client):
197
198
  fill_query_params(kwargs.pop("path"), shipment_id), data={**data, **kwargs}
198
199
  )
199
200
 
201
+ @sp_endpoint(
202
+ "/inbound/fba/<version>/inboundPlans/{}/shipments/{}/name", method="PUT"
203
+ )
204
+ def update_shipment_name(self, inboundPlanId, shipmentId, **kwargs):
205
+ """
206
+ update_shipment_name(self, inboundPlanId, shipmentId, **kwargs) -> ApiResponse
207
+
208
+ Updates the name of an existing shipment.
209
+
210
+ **Usage Plan:**
211
+
212
+ | Rate (requests per second) | Burst |
213
+ | ---- | ---- |
214
+ | 2 | 30 |
215
+
216
+ The `x-amzn-RateLimit-Limit` response header returns the usage plan rate limits that were applied to the requested operation, when available. The table above indicates the default rate and burst values for this operation. Selling partners whose business demands require higher throughput may see higher rate and burst values than those shown here. For more information, refer to [Usage Plans and Rate Limits in the Selling Partner API](https://developer-docs.amazon.com/sp-api/docs/usage-plans-and-rate-limits-in-the-sp-api).
217
+
218
+ Args:
219
+
220
+ inboundPlanId:string | * REQUIRED Identifier to an inbound plan.
221
+
222
+ shipmentId:string | * REQUIRED Identifier to a shipment. A shipment contains the boxes and units being inbounded.
223
+
224
+ body: | * REQUIRED {'name': {'description': 'A human-readable name to update the shipment name to.'}, 'type': 'string'}
225
+
226
+ Returns:
227
+ ApiResponse:
228
+ """
229
+ return self._request(
230
+ fill_query_params(kwargs.pop("path"), inboundPlanId, shipmentId),
231
+ data=kwargs,
232
+ )
233
+
200
234
  @sp_endpoint("/fba/inbound/<version>/shipments/{}/preorder")
201
235
  def preorder(self, shipment_id, **kwargs):
202
236
  """
@@ -456,8 +490,7 @@ class FulfillmentInbound(Client):
456
490
  Returns:
457
491
  ApiResponse
458
492
  """
459
- if not isinstance(shipment_id_list, str):
460
- shipment_id_list = ",".join(shipment_id_list)
493
+ shipment_id_list = ensure_csv(shipment_id_list)
461
494
  return self.get_shipments(
462
495
  QueryType="SHIPMENT", ShipmentIdList=shipment_id_list, **kwargs
463
496
  )
@@ -1,8 +1,8 @@
1
- from collections import abc
2
1
  import urllib
3
2
 
4
3
  from sp_api.base import Client, Marketplaces, sp_endpoint, ApiResponse
5
4
  from sp_api.base.InventoryEnums import InventoryGranularity
5
+ from sp_api.util import normalize_csv_param
6
6
 
7
7
 
8
8
  class Inventories(Client):
@@ -68,11 +68,6 @@ class Inventories(Client):
68
68
  "granularityId": kwargs.get("granularityId", self.marketplace_id),
69
69
  }
70
70
  )
71
- if (
72
- "sellerSkus" in kwargs
73
- and isinstance(kwargs.get("sellerSkus"), abc.Iterable)
74
- and not isinstance(kwargs.get("sellerSkus"), str)
75
- ):
76
- kwargs.update({"sellerSkus": ",".join(kwargs.get("sellerSkus"))})
71
+ normalize_csv_param(kwargs, "sellerSkus")
77
72
 
78
73
  return self._request(kwargs.pop("path"), params=kwargs)
@@ -1,5 +1,3 @@
1
- from collections import abc
2
-
3
1
  from sp_api.base import (
4
2
  Client,
5
3
  sp_endpoint,
@@ -7,6 +5,7 @@ from sp_api.base import (
7
5
  ApiResponse,
8
6
  IncludedData,
9
7
  )
8
+ from sp_api.util import normalize_included_data
10
9
 
11
10
 
12
11
  class ListingsItems(Client):
@@ -65,17 +64,7 @@ class ListingsItems(Client):
65
64
  Returns:
66
65
  ApiResponse:
67
66
  """
68
- if (
69
- kwargs.get("includedData")
70
- and isinstance(kwargs.get("includedData"), abc.Iterable)
71
- and not isinstance(kwargs.get("includedData"), str)
72
- ):
73
- kwargs["includedData"] = ",".join(
74
- [
75
- x.value if isinstance(x, IncludedData) else x
76
- for x in kwargs["includedData"]
77
- ]
78
- )
67
+ normalize_included_data(kwargs, enum_cls=IncludedData)
79
68
 
80
69
  return self._request(
81
70
  fill_query_params(kwargs.pop("path"), sellerId, sku), params=kwargs
@@ -101,17 +90,7 @@ class ListingsItems(Client):
101
90
  Returns:
102
91
  ApiResponse:
103
92
  """
104
- if (
105
- kwargs.get("includedData")
106
- and isinstance(kwargs.get("includedData"), abc.Iterable)
107
- and not isinstance(kwargs.get("includedData"), str)
108
- ):
109
- kwargs["includedData"] = ",".join(
110
- [
111
- x.value if isinstance(x, IncludedData) else x
112
- for x in kwargs["includedData"]
113
- ]
114
- )
93
+ normalize_included_data(kwargs, enum_cls=IncludedData)
115
94
 
116
95
  return self._request(
117
96
  fill_query_params(kwargs.pop("path"), sellerId), params=kwargs
@@ -466,3 +466,45 @@ class Messaging(Client):
466
466
  "method": kwargs.pop("method"),
467
467
  },
468
468
  )
469
+
470
+ @sp_endpoint("/messaging/v1/orders/{}/messages/invoice", method="POST")
471
+ def send_invoice(self, order_id, **kwargs) -> ApiResponse:
472
+ """
473
+ send_invoice(self, order_id, **kwargs) -> ApiResponse
474
+
475
+ Sends a message providing the buyer an invoice
476
+
477
+ **Usage Plan:**
478
+
479
+ ====================================== ==============
480
+ Rate (requests per second) Burst
481
+ ====================================== ==============
482
+ 1 5
483
+ ====================================== ==============
484
+
485
+ For more information, see "Usage Plans and Rate Limits" in the Selling Partner API documentation.
486
+
487
+ Args:
488
+ order_id:string | * REQUIRED An Amazon order identifier. This specifies the order for which a message is sent.
489
+ body: {
490
+ "attachments": [
491
+ {
492
+ "uploadDestinationId": "string",
493
+ "fileName": "string"
494
+ }
495
+ ]
496
+ }
497
+
498
+
499
+ Returns:
500
+ ApiResponse:
501
+ """
502
+
503
+ return self._request(
504
+ fill_query_params(kwargs.pop("path"), order_id),
505
+ data=kwargs.pop("body"),
506
+ params={
507
+ "marketplaceIds": self.marketplace_id,
508
+ "method": kwargs.pop("method"),
509
+ },
510
+ )
@@ -1,5 +1,6 @@
1
1
  from sp_api.base import sp_endpoint, fill_query_params, ApiResponse, deprecated
2
2
  from sp_api.base import Client, Marketplaces
3
+ from sp_api.util import normalize_csv_param
3
4
 
4
5
 
5
6
  class Orders(Client):
@@ -53,6 +54,12 @@ class Orders(Client):
53
54
 
54
55
 
55
56
  """
57
+ normalize_csv_param(kwargs, "OrderStatuses")
58
+ normalize_csv_param(kwargs, "MarketplaceIds")
59
+ normalize_csv_param(kwargs, "FulfillmentChannels")
60
+ normalize_csv_param(kwargs, "PaymentMethods")
61
+ normalize_csv_param(kwargs, "AmazonOrderIds")
62
+
56
63
  if "RestrictedResources" in kwargs:
57
64
  return self._access_restricted(kwargs)
58
65
  return self._request(kwargs.pop("path"), params={**kwargs})
@@ -3,6 +3,7 @@ from urllib.parse import quote_plus
3
3
 
4
4
  from sp_api.base.helpers import sp_endpoint, fill_query_params
5
5
  from sp_api.base import Client, ApiResponse
6
+ from sp_api.util.product_fees import create_fees_body
6
7
 
7
8
 
8
9
  class ProductFees(Client):
@@ -63,15 +64,15 @@ class ProductFees(Client):
63
64
  seller_sku = quote_plus(seller_sku)
64
65
 
65
66
  kwargs.update(
66
- self._create_body(
67
- price,
68
- shipping_price,
69
- currency,
70
- is_fba,
71
- seller_sku,
72
- points,
73
- marketplace_id,
74
- optional_fulfillment_program,
67
+ create_fees_body(
68
+ price=price,
69
+ shipping_price=shipping_price,
70
+ currency=currency,
71
+ is_fba=is_fba,
72
+ identifier=seller_sku,
73
+ points=points,
74
+ marketplace_id=marketplace_id or self.marketplace_id,
75
+ optional_fulfillment_program=optional_fulfillment_program,
75
76
  )
76
77
  )
77
78
  return self._request(
@@ -124,15 +125,15 @@ class ProductFees(Client):
124
125
 
125
126
  """
126
127
  kwargs.update(
127
- self._create_body(
128
- price,
129
- shipping_price,
130
- currency,
131
- is_fba,
132
- asin,
133
- points,
134
- marketplace_id,
135
- optional_fulfillment_program,
128
+ create_fees_body(
129
+ price=price,
130
+ shipping_price=shipping_price,
131
+ currency=currency,
132
+ is_fba=is_fba,
133
+ identifier=asin,
134
+ points=points,
135
+ marketplace_id=marketplace_id or self.marketplace_id,
136
+ optional_fulfillment_program=optional_fulfillment_program,
136
137
  )
137
138
  )
138
139
  return self._request(fill_query_params(kwargs.pop("path"), asin), data=kwargs)
@@ -166,7 +167,18 @@ class ProductFees(Client):
166
167
  marketplace_id: str | Defaults to self.marketplace_id
167
168
  optional_fulfillment_program:
168
169
  """
169
- data = [dict(**self._create_body(**er)) for er in estimate_requests]
170
+ data = []
171
+ for estimate in estimate_requests:
172
+ estimate_payload = dict(estimate)
173
+ marketplace_id = estimate_payload.pop("marketplace_id", None)
174
+ data.append(
175
+ dict(
176
+ **create_fees_body(
177
+ marketplace_id=marketplace_id or self.marketplace_id,
178
+ **estimate_payload,
179
+ )
180
+ )
181
+ )
170
182
  return self._request(
171
183
  "/products/fees/v0/feesEstimate",
172
184
  data=data,
@@ -174,61 +186,6 @@ class ProductFees(Client):
174
186
  wrap_list=True,
175
187
  )
176
188
 
177
- def _create_body(
178
- self,
179
- price,
180
- shipping_price=None,
181
- currency="USD",
182
- is_fba=False,
183
- identifier=None,
184
- points: dict = None,
185
- marketplace_id: str = None,
186
- optional_fulfillment_program: str = None,
187
- id_type=None,
188
- id_value=None,
189
- ):
190
- """
191
- Create request body
192
-
193
- Args:
194
- price:
195
- shipping_price:
196
- currency:
197
- is_fba:
198
- identifier:
199
- points:
200
-
201
- Returns:
202
-
203
- """
204
- body = {
205
- "FeesEstimateRequest": {
206
- "Identifier": identifier or str(price),
207
- "PriceToEstimateFees": {
208
- "ListingPrice": {"Amount": price, "CurrencyCode": currency},
209
- "Shipping": (
210
- {"Amount": shipping_price, "CurrencyCode": currency}
211
- if shipping_price
212
- else None
213
- ),
214
- "Points": points or None,
215
- },
216
- "IsAmazonFulfilled": is_fba,
217
- "OptionalFulfillmentProgram": (
218
- optional_fulfillment_program
219
- if is_fba is True and optional_fulfillment_program
220
- else None
221
- ),
222
- "MarketplaceId": marketplace_id or self.marketplace_id,
223
- }
224
- }
225
-
226
- if id_type and id_value:
227
- body["IdType"] = id_type
228
- body["IdValue"] = id_value
229
-
230
- return body
231
-
232
189
  def _add_marketplaces(self, data):
233
190
  # MarketplaceID is a property of the body's FeesEstimateRequest for this section, and does
234
191
  # not need to be added. Additionally, Client._add_marketplaces will fail as it assumes
@@ -7,6 +7,7 @@ from sp_api.api.products.products_definitions import (
7
7
  GetItemOffersBatchRequest,
8
8
  GetListingOffersBatchRequest,
9
9
  )
10
+ from sp_api.util import ensure_csv
10
11
 
11
12
 
12
13
  class Products(Client):
@@ -377,10 +378,11 @@ class Products(Client):
377
378
  )
378
379
 
379
380
  def _create_get_pricing_request(self, item_list, item_type, **kwargs):
381
+ items_csv = ensure_csv(item_list)
380
382
  return self._request(
381
383
  kwargs.pop("path"),
382
384
  params={
383
- **{f"{item_type}s": ",".join(item_list)},
385
+ **{f"{item_type}s": items_csv},
384
386
  "ItemType": item_type,
385
387
  **(
386
388
  {"ItemCondition": kwargs.pop("ItemCondition")}
@@ -1,169 +1,11 @@
1
- from enum import Enum
2
- from typing import Optional, List, Dict, Union
3
- from dataclasses import dataclass, asdict
4
-
5
-
6
- class CompetitiveSummaryIncludedData(Enum):
7
- FEATURED_BUYING_OPTIONS = "featuredBuyingOptions"
8
- LOWEST_PRICED_OFFERS = "lowestPricedOffers"
9
- REFERENCE_PRICES = "referencePrices"
10
-
11
-
12
- @dataclass
13
- class ItemOffersRequest:
14
- """Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference
15
- #itemoffersrequest"""
16
-
17
- uri: str
18
- method: str
19
- MarketplaceId: str
20
- ItemCondition: str = None
21
- CustomerType: str = None
22
- headers: Dict = None
23
-
24
-
25
- @dataclass
26
- class GetItemOffersBatchRequest:
27
- """Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference
28
- #getitemoffersbatchrequest"""
29
-
30
- requests: Optional[List[Union[ItemOffersRequest, Dict]]] = None
31
-
32
- def __post_init__(self):
33
- self.requests = self.parse_requests(self.requests)
34
-
35
- def to_dict(self):
36
- return asdict(self)
37
-
38
- @staticmethod
39
- def parse_requests(requests) -> List[ItemOffersRequest]:
40
- parsed_requestes = []
41
-
42
- for request in requests:
43
- if isinstance(request, Dict):
44
- request = ItemOffersRequest(**request)
45
-
46
- if not isinstance(request, ItemOffersRequest):
47
- raise TypeError
48
-
49
- parsed_requestes.append(request)
50
-
51
- return parsed_requestes
52
-
53
-
54
- @dataclass
55
- class ListingOffersRequest:
56
- """Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference
57
- #listingoffersrequest"""
58
-
59
- uri: str
60
- MarketplaceId: str
61
- ItemCondition: str
62
- method: str = "GET"
63
- CustomerType: str = "Consumer"
64
-
65
-
66
- @dataclass
67
- class GetListingOffersBatchRequest:
68
- """Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference
69
- #getlistingoffersbatchrequest"""
70
-
71
- requests: Optional[List[Union[ListingOffersRequest, Dict]]] = None
72
-
73
- def __post_init__(self):
74
- self.requests = self.parse_requests(self.requests)
75
-
76
- def to_dict(self):
77
- return asdict(self)
78
-
79
- @staticmethod
80
- def parse_requests(requests) -> List[ListingOffersRequest]:
81
- parsed_requestes = []
82
-
83
- for request in requests:
84
- if isinstance(request, Dict):
85
- request = ListingOffersRequest(**request)
86
-
87
- if not isinstance(request, ListingOffersRequest):
88
- raise TypeError
89
-
90
- parsed_requestes.append(request)
91
-
92
- return parsed_requestes
93
-
94
-
95
- @dataclass
96
- class FeaturedOfferExpectedPriceRequest:
97
- """ Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v2022-05-01-reference
98
- #FeaturedOfferExpectedPriceRequest """
99
- marketplaceId: str
100
- sku: str
101
- uri: str = "/products/pricing/2022-05-01/offer/featuredOfferExpectedPrice"
102
- method: str = "GET"
103
-
104
-
105
- @dataclass
106
- class GetFeaturedOfferExpectedPriceBatch:
107
- """ Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v2022-05-01-reference
108
- #getFeaturedOfferExpectedPriceBatch """
109
- requests: Optional[List[Union[FeaturedOfferExpectedPriceRequest, Dict]]] = None
110
-
111
- def __post_init__(self):
112
- self.requests = self.parse_requests(self.requests)
113
-
114
- def to_dict(self):
115
- return asdict(self)
116
-
117
- @staticmethod
118
- def parse_requests(requests) -> List[FeaturedOfferExpectedPriceRequest]:
119
- parsed_requests = []
120
-
121
- for request in requests:
122
- if isinstance(request, Dict):
123
- request = FeaturedOfferExpectedPriceRequest(**request)
124
-
125
- if not isinstance(request, FeaturedOfferExpectedPriceRequest):
126
- raise TypeError
127
-
128
- parsed_requests.append(request)
129
-
130
- return parsed_requests
131
-
132
-
133
- @dataclass
134
- class CompetitiveSummaryRequest:
135
- """ Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v2022-05-01-reference
136
- #FeaturedOfferExpectedPriceRequest """
137
- marketplaceId: str
138
- asin: str
139
- includedData: List[CompetitiveSummaryIncludedData]
140
- uri: str = "/products/pricing/2022-05-01/items/competitiveSummary"
141
- method: str = "GET"
142
-
143
-
144
- @dataclass
145
- class GetCompetitiveSummaryBatch:
146
- """ Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v2022-05-01-reference
147
- #getCompetitiveSummary """
148
- requests: Optional[List[Union[CompetitiveSummaryRequest, Dict]]] = None
149
-
150
- def __post_init__(self):
151
- self.requests = self.parse_requests(self.requests)
152
-
153
- def to_dict(self):
154
- return asdict(self)
155
-
156
- @staticmethod
157
- def parse_requests(requests) -> List[CompetitiveSummaryRequest]:
158
- parsed_requests = []
159
-
160
- for request in requests:
161
- if isinstance(request, Dict):
162
- request = CompetitiveSummaryRequest(**request)
163
-
164
- if not isinstance(request, CompetitiveSummaryRequest):
165
- raise TypeError
166
-
167
- parsed_requests.append(request)
168
-
169
- return parsed_requests
1
+ from sp_api.util.products_definitions import (
2
+ CompetitiveSummaryIncludedData,
3
+ ItemOffersRequest,
4
+ GetItemOffersBatchRequest,
5
+ ListingOffersRequest,
6
+ GetListingOffersBatchRequest,
7
+ FeaturedOfferExpectedPriceRequest,
8
+ GetFeaturedOfferExpectedPriceBatch,
9
+ CompetitiveSummaryRequest,
10
+ GetCompetitiveSummaryBatch,
11
+ )