python-amazon-sp-api 1.9.39__py3-none-any.whl → 2.0.10__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 (163) hide show
  1. {python_amazon_sp_api-1.9.39.dist-info → python_amazon_sp_api-2.0.10.dist-info}/METADATA +44 -8
  2. python_amazon_sp_api-2.0.10.dist-info/RECORD +253 -0
  3. {python_amazon_sp_api-1.9.39.dist-info → python_amazon_sp_api-2.0.10.dist-info}/WHEEL +1 -1
  4. {python_amazon_sp_api-1.9.39.dist-info → python_amazon_sp_api-2.0.10.dist-info}/top_level.txt +0 -1
  5. sp_api/__version__.py +1 -1
  6. sp_api/api/__init__.py +9 -3
  7. sp_api/api/application_integrations/application_integrations.py +2 -2
  8. sp_api/api/catalog/catalog.py +3 -4
  9. sp_api/api/catalog_items/catalog_items.py +3 -6
  10. sp_api/api/customer_feedback/customer_feedback.py +110 -0
  11. sp_api/api/data_kiosk/data_kiosk.py +5 -6
  12. sp_api/api/easy_ship/easy_ship.py +5 -5
  13. sp_api/api/external_fulfillment/external_fulfillment.py +706 -0
  14. sp_api/api/feeds/feeds.py +11 -8
  15. sp_api/api/fulfillment_inbound/fulfillment_inbound.py +35 -2
  16. sp_api/api/inventories/inventories.py +2 -7
  17. sp_api/api/listings_items/listings_items.py +3 -24
  18. sp_api/api/messaging/messaging.py +42 -0
  19. sp_api/api/orders/orders.py +59 -3
  20. sp_api/api/orders/orders_2026_01_01.py +54 -0
  21. sp_api/api/product_fees/product_fees.py +31 -74
  22. sp_api/api/products/products.py +3 -1
  23. sp_api/api/products/products_definitions.py +11 -169
  24. sp_api/api/reports/reports.py +61 -96
  25. sp_api/api/sales/sales.py +2 -2
  26. sp_api/asyncio/api/__init__.py +167 -0
  27. sp_api/asyncio/api/amazon_warehousing_and_distribu/__init__.py +9 -0
  28. sp_api/asyncio/api/amazon_warehousing_and_distribu/amazon_warehousing_and_distribu.py +130 -0
  29. sp_api/asyncio/api/aplus_content/__init__.py +5 -0
  30. sp_api/asyncio/api/aplus_content/aplus_content.py +330 -0
  31. sp_api/asyncio/api/application_integrations/__init__.py +5 -0
  32. sp_api/asyncio/api/application_integrations/application_integrations.py +119 -0
  33. sp_api/asyncio/api/application_management/__init__.py +5 -0
  34. sp_api/asyncio/api/application_management/application_management.py +36 -0
  35. sp_api/asyncio/api/authorization/__init__.py +5 -0
  36. sp_api/asyncio/api/authorization/authorization.py +54 -0
  37. sp_api/asyncio/api/catalog/__init__.py +5 -0
  38. sp_api/asyncio/api/catalog/catalog.py +111 -0
  39. sp_api/asyncio/api/catalog_items/__init__.py +6 -0
  40. sp_api/asyncio/api/catalog_items/catalog_items.py +93 -0
  41. sp_api/asyncio/api/clients/__init__.py +1 -0
  42. sp_api/asyncio/api/customer_feedback/__init__.py +5 -0
  43. sp_api/asyncio/api/customer_feedback/customer_feedback.py +111 -0
  44. sp_api/asyncio/api/data_kiosk/__init__.py +5 -0
  45. sp_api/asyncio/api/data_kiosk/data_kiosk.py +236 -0
  46. sp_api/asyncio/api/easy_ship/__init__.py +5 -0
  47. sp_api/asyncio/api/easy_ship/easy_ship.py +191 -0
  48. sp_api/asyncio/api/external_fulfillment/__init__.py +5 -0
  49. sp_api/asyncio/api/external_fulfillment/external_fulfillment.py +706 -0
  50. sp_api/asyncio/api/fba_inbound_eligibility/__init__.py +5 -0
  51. sp_api/asyncio/api/fba_inbound_eligibility/fba_inbound_eligibility.py +96 -0
  52. sp_api/asyncio/api/fba_small_and_light/__init__.py +5 -0
  53. sp_api/asyncio/api/fba_small_and_light/fba_small_and_light.py +213 -0
  54. sp_api/asyncio/api/feeds/feeds.py +260 -0
  55. sp_api/asyncio/api/finances/finances.py +100 -0
  56. sp_api/asyncio/api/fulfillment_inbound/fulfillment_inbound.py +1798 -0
  57. sp_api/asyncio/api/fulfillment_outbound/fulfillment_outbound.py +736 -0
  58. sp_api/asyncio/api/inventories/inventories.py +74 -0
  59. sp_api/asyncio/api/listings_items/listings_items.py +170 -0
  60. sp_api/asyncio/api/listings_restrictions/listings_restrictions.py +36 -0
  61. sp_api/asyncio/api/merchant_fulfillment/__init__.py +0 -0
  62. sp_api/asyncio/api/merchant_fulfillment/merchant_fulfillment.py +384 -0
  63. sp_api/asyncio/api/messaging/__init__.py +0 -0
  64. sp_api/asyncio/api/messaging/messaging.py +511 -0
  65. sp_api/asyncio/api/models/__init__.py +4 -0
  66. sp_api/asyncio/api/notifications/__init__.py +0 -0
  67. sp_api/asyncio/api/notifications/notifications.py +295 -0
  68. sp_api/asyncio/api/orders/__init__.py +0 -0
  69. sp_api/asyncio/api/orders/orders.py +412 -0
  70. sp_api/asyncio/api/orders/orders_2026_01_01.py +40 -0
  71. sp_api/asyncio/api/overrides/__init__.py +1 -0
  72. sp_api/asyncio/api/product_fees/__init__.py +0 -0
  73. sp_api/asyncio/api/product_fees/product_fees.py +194 -0
  74. sp_api/asyncio/api/product_type_definitions/__init__.py +0 -0
  75. sp_api/asyncio/api/product_type_definitions/product_type_definitions.py +75 -0
  76. sp_api/asyncio/api/products/__init__.py +0 -0
  77. sp_api/asyncio/api/products/products.py +405 -0
  78. sp_api/asyncio/api/products/products_definitions.py +11 -0
  79. sp_api/asyncio/api/replenishment/__init__.py +0 -0
  80. sp_api/asyncio/api/replenishment/replenishment.py +121 -0
  81. sp_api/asyncio/api/reports/__init__.py +0 -0
  82. sp_api/asyncio/api/reports/reports.py +439 -0
  83. sp_api/asyncio/api/sales/__init__.py +0 -0
  84. sp_api/asyncio/api/sales/sales.py +93 -0
  85. sp_api/asyncio/api/sellers/__init__.py +0 -0
  86. sp_api/asyncio/api/sellers/sellers.py +70 -0
  87. sp_api/asyncio/api/services/__init__.py +0 -0
  88. sp_api/asyncio/api/services/services.py +218 -0
  89. sp_api/asyncio/api/shipping/__init__.py +0 -0
  90. sp_api/asyncio/api/shipping/shipping.py +459 -0
  91. sp_api/asyncio/api/shipping/shippingV2.py +651 -0
  92. sp_api/asyncio/api/solicitations/__init__.py +0 -0
  93. sp_api/asyncio/api/solicitations/solicitations.py +78 -0
  94. sp_api/asyncio/api/supply_sources/__init__.py +0 -0
  95. sp_api/asyncio/api/supply_sources/supply_sources.py +138 -0
  96. sp_api/asyncio/api/tokens/__init__.py +0 -0
  97. sp_api/asyncio/api/tokens/tokens.py +65 -0
  98. sp_api/asyncio/api/upload/__init__.py +0 -0
  99. sp_api/asyncio/api/upload/upload.py +18 -0
  100. sp_api/asyncio/api/vendor_direct_fulfillment_inventory/__init__.py +0 -0
  101. sp_api/asyncio/api/vendor_direct_fulfillment_inventory/vendor_direct_fulfillment_inventory.py +64 -0
  102. sp_api/asyncio/api/vendor_direct_fulfillment_orders/__init__.py +0 -0
  103. sp_api/asyncio/api/vendor_direct_fulfillment_orders/vendor_direct_fulfillment_orders.py +196 -0
  104. sp_api/asyncio/api/vendor_direct_fulfillment_payments/__init__.py +0 -0
  105. sp_api/asyncio/api/vendor_direct_fulfillment_payments/vendor_direct_fulfillment_payments.py +254 -0
  106. sp_api/asyncio/api/vendor_direct_fulfillment_shipping/__init__.py +0 -0
  107. sp_api/asyncio/api/vendor_direct_fulfillment_shipping/vendor_direct_fulfillment_shipping.py +627 -0
  108. sp_api/asyncio/api/vendor_direct_fulfillment_transactions/__init__.py +0 -0
  109. sp_api/asyncio/api/vendor_direct_fulfillment_transactions/vendor_direct_fulfillment_transactions.py +43 -0
  110. sp_api/asyncio/api/vendor_invoices/__init__.py +0 -0
  111. sp_api/asyncio/api/vendor_invoices/vendor_invoices.py +295 -0
  112. sp_api/asyncio/api/vendor_orders/__init__.py +0 -0
  113. sp_api/asyncio/api/vendor_orders/vendor_orders.py +210 -0
  114. sp_api/asyncio/api/vendor_shipments/__init__.py +0 -0
  115. sp_api/asyncio/api/vendor_shipments/vendor_shipments.py +118 -0
  116. sp_api/asyncio/api/vendor_transaction_status/__init__.py +0 -0
  117. sp_api/asyncio/api/vendor_transaction_status/vendor_transaction_status.py +41 -0
  118. sp_api/asyncio/auth/__init__.py +12 -0
  119. sp_api/asyncio/auth/access_token_client.py +145 -0
  120. sp_api/asyncio/auth/exceptions.py +5 -0
  121. sp_api/asyncio/base/__init__.py +53 -0
  122. sp_api/asyncio/base/_transport_httpx.py +50 -0
  123. sp_api/asyncio/base/base_client.py +8 -0
  124. sp_api/asyncio/base/client.py +169 -0
  125. sp_api/asyncio/util/__init__.py +29 -0
  126. sp_api/asyncio/util/key_maker.py +5 -0
  127. sp_api/asyncio/util/load_all_pages.py +55 -0
  128. sp_api/asyncio/util/load_date_bound.py +53 -0
  129. sp_api/asyncio/util/retry.py +88 -0
  130. sp_api/auth/_core.py +39 -0
  131. sp_api/auth/access_token_client.py +18 -29
  132. sp_api/base/ApiResponse.py +2 -2
  133. sp_api/base/_core.py +110 -0
  134. sp_api/base/_transport_httpx.py +39 -0
  135. sp_api/base/client.py +40 -63
  136. sp_api/base/helpers.py +1 -1
  137. sp_api/util/__init__.py +36 -0
  138. sp_api/util/params.py +57 -0
  139. sp_api/util/product_fees.py +40 -0
  140. sp_api/util/products_definitions.py +169 -0
  141. sp_api/util/report_document.py +154 -0
  142. python_amazon_sp_api-1.9.39.dist-info/RECORD +0 -148
  143. tests/api/finances/test_finances.py +0 -19
  144. tests/api/notifications/test_notifications.py +0 -26
  145. tests/api/orders/test_orders.py +0 -122
  146. tests/api/product_fees/product_fees.py +0 -49
  147. tests/api/reports/test_reports.py +0 -127
  148. tests/client/test_auth.py +0 -59
  149. tests/client/test_base.py +0 -163
  150. tests/client/test_credential_provider.py +0 -45
  151. tests/client/test_helpers.py +0 -142
  152. {python_amazon_sp_api-1.9.39.data → python_amazon_sp_api-2.0.10.data}/scripts/make_endpoint +0 -0
  153. {python_amazon_sp_api-1.9.39.dist-info → python_amazon_sp_api-2.0.10.dist-info}/licenses/LICENSE +0 -0
  154. {tests → sp_api/api/customer_feedback}/__init__.py +0 -0
  155. {tests/api → sp_api/api/external_fulfillment}/__init__.py +0 -0
  156. {tests/api/finances → sp_api/asyncio}/__init__.py +0 -0
  157. {tests/api/notifications → sp_api/asyncio/api/feeds}/__init__.py +0 -0
  158. {tests/api/orders → sp_api/asyncio/api/finances}/__init__.py +0 -0
  159. {tests/api/product_fees → sp_api/asyncio/api/fulfillment_inbound}/__init__.py +0 -0
  160. {tests/api/reports → sp_api/asyncio/api/fulfillment_outbound}/__init__.py +0 -0
  161. {tests/api/sellers → sp_api/asyncio/api/inventories}/__init__.py +0 -0
  162. {tests/client → sp_api/asyncio/api/listings_items}/__init__.py +0 -0
  163. /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,12 +1,61 @@
1
- from sp_api.base import sp_endpoint, fill_query_params, ApiResponse, deprecated
2
- from sp_api.base import Client, Marketplaces
1
+ from __future__ import annotations
2
+
3
+ import enum
4
+ from typing import Any, Literal, overload
5
+
6
+ from sp_api.base import ApiResponse, Client, Marketplaces, deprecated, fill_query_params, sp_endpoint
7
+ from sp_api.util import normalize_csv_param
8
+
9
+ from .orders_2026_01_01 import OrdersV20260101
10
+
11
+
12
+ class OrdersVersion(str, enum.Enum):
13
+ V0 = "v0" # legacy
14
+ V_2026_01_01 = "2026-01-01"
15
+ LATEST = "2026-01-01"
3
16
 
4
17
 
5
18
  class Orders(Client):
6
- """
19
+ """Orders API client.
20
+
21
+ This class implements the legacy Orders API **v0**.
22
+
23
+ If you pass version "2026-01-01" (or :class:`OrdersVersion.V_2026_01_01`)
24
+ to the constructor, :meth:`__new__` returns an instance of
25
+ :class:`~sp_api.api.orders.orders_2026_01_01.OrdersV20260101` instead.
26
+
7
27
  :link: https://github.com/amzn/selling-partner-api-docs/tree/main/references/orders-api
8
28
  """
9
29
 
30
+ @overload
31
+ def __new__(
32
+ cls,
33
+ *args: Any,
34
+ version: Literal[OrdersVersion.V_2026_01_01, "2026-01-01"],
35
+ **kwargs: Any,
36
+ ) -> OrdersV20260101: ...
37
+
38
+ @overload
39
+ def __new__(
40
+ cls,
41
+ *args: Any,
42
+ version: str | OrdersVersion | None = None,
43
+ **kwargs: Any,
44
+ ) -> "Orders": ...
45
+
46
+ def __new__(
47
+ cls,
48
+ *args: Any,
49
+ version: str | OrdersVersion | None = None,
50
+ **kwargs: Any,
51
+ ):
52
+ if cls is Orders:
53
+ v = version if version is not None else kwargs.get("version")
54
+ if v in (OrdersVersion.V_2026_01_01, OrdersVersion.LATEST, "2026-01-01"):
55
+ kwargs.pop("version", None)
56
+ return OrdersV20260101(*args, **kwargs)
57
+ return super().__new__(cls)
58
+
10
59
  @sp_endpoint("/orders/v0/orders")
11
60
  def get_orders(self, **kwargs) -> ApiResponse:
12
61
  """
@@ -53,6 +102,12 @@ class Orders(Client):
53
102
 
54
103
 
55
104
  """
105
+ normalize_csv_param(kwargs, "OrderStatuses")
106
+ normalize_csv_param(kwargs, "MarketplaceIds")
107
+ normalize_csv_param(kwargs, "FulfillmentChannels")
108
+ normalize_csv_param(kwargs, "PaymentMethods")
109
+ normalize_csv_param(kwargs, "AmazonOrderIds")
110
+
56
111
  if "RestrictedResources" in kwargs:
57
112
  return self._access_restricted(kwargs)
58
113
  return self._request(kwargs.pop("path"), params={**kwargs})
@@ -353,3 +408,4 @@ class Orders(Client):
353
408
  if not self.keep_restricted_data_token:
354
409
  self.restricted_data_token = None
355
410
  return r
411
+
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any
4
+
5
+ from sp_api.base import ApiResponse, Client, fill_query_params, sp_endpoint
6
+ from sp_api.util import normalize_csv_param
7
+
8
+
9
+ class OrdersV20260101(Client):
10
+ """Orders API (version 2026-01-01).
11
+
12
+ This is a newer Orders API version that uses different endpoints/parameters
13
+ than the legacy v0 Orders API implemented by :class:`sp_api.api.orders.orders.Orders`.
14
+
15
+ Model source:
16
+ https://github.com/amzn/selling-partner-api-models/blob/main/models/orders-api-model/orders_2026-01-01.json
17
+ """
18
+
19
+ @sp_endpoint("/orders/2026-01-01/orders")
20
+ def search_orders(self, **kwargs: Any) -> ApiResponse:
21
+ """Search orders.
22
+
23
+ Corresponds to GET /orders/2026-01-01/orders (operationId: searchOrders).
24
+
25
+ Notes:
26
+ - Parameters are lowerCamelCase in this version (e.g. createdAfter).
27
+ - List parameters can be passed as Python lists; they will be normalized
28
+ into a comma-delimited string.
29
+ """
30
+
31
+ normalize_csv_param(kwargs, "fulfillmentStatuses")
32
+ normalize_csv_param(kwargs, "marketplaceIds")
33
+ normalize_csv_param(kwargs, "fulfilledBy")
34
+ normalize_csv_param(kwargs, "includedData")
35
+
36
+ return self._request(kwargs.pop("path"), params={**kwargs})
37
+
38
+ @sp_endpoint("/orders/2026-01-01/orders/{}")
39
+ def get_order(self, order_id: str, **kwargs: Any) -> ApiResponse:
40
+ """Get order by orderId.
41
+
42
+ Corresponds to GET /orders/2026-01-01/orders/{orderId} (operationId: getOrder).
43
+
44
+ Args:
45
+ order_id: The Amazon order identifier.
46
+ includedData: Optional list of datasets to include in the response.
47
+ """
48
+
49
+ normalize_csv_param(kwargs, "includedData")
50
+ return self._request(
51
+ fill_query_params(kwargs.pop("path"), order_id),
52
+ params={**kwargs},
53
+ add_marketplace=False,
54
+ )
@@ -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")}