python-amazon-sp-api 1.9.18__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.
- {python_amazon_sp_api-1.9.18.data → python_amazon_sp_api-2.0.7.data}/scripts/make_endpoint +2 -2
- {python_amazon_sp_api-1.9.18.dist-info → python_amazon_sp_api-2.0.7.dist-info}/METADATA +46 -23
- python_amazon_sp_api-2.0.7.dist-info/RECORD +251 -0
- {python_amazon_sp_api-1.9.18.dist-info → python_amazon_sp_api-2.0.7.dist-info}/WHEEL +1 -1
- {python_amazon_sp_api-1.9.18.dist-info → python_amazon_sp_api-2.0.7.dist-info}/top_level.txt +0 -1
- sp_api/__version__.py +1 -1
- sp_api/api/__init__.py +18 -1
- sp_api/api/application_integrations/application_integrations.py +118 -0
- sp_api/api/application_management/application_management.py +2 -1
- sp_api/api/catalog/catalog.py +3 -4
- sp_api/api/catalog_items/catalog_items.py +3 -6
- sp_api/api/customer_feedback/customer_feedback.py +110 -0
- sp_api/api/data_kiosk/data_kiosk.py +5 -6
- sp_api/api/easy_ship/easy_ship.py +190 -0
- sp_api/api/external_fulfillment/external_fulfillment.py +706 -0
- sp_api/api/feeds/feeds.py +11 -8
- sp_api/api/finances/finances.py +30 -4
- sp_api/api/fulfillment_inbound/fulfillment_inbound.py +35 -2
- sp_api/api/inventories/inventories.py +2 -7
- sp_api/api/listings_items/listings_items.py +3 -24
- sp_api/api/messaging/messaging.py +42 -0
- sp_api/api/orders/orders.py +7 -0
- sp_api/api/product_fees/product_fees.py +31 -74
- sp_api/api/products/products.py +80 -2
- sp_api/api/products/products_definitions.py +11 -85
- sp_api/api/reports/reports.py +65 -97
- sp_api/api/sales/sales.py +2 -2
- sp_api/asyncio/api/__init__.py +164 -0
- sp_api/asyncio/api/amazon_warehousing_and_distribu/__init__.py +9 -0
- sp_api/asyncio/api/amazon_warehousing_and_distribu/amazon_warehousing_and_distribu.py +130 -0
- sp_api/asyncio/api/aplus_content/__init__.py +5 -0
- sp_api/asyncio/api/aplus_content/aplus_content.py +330 -0
- sp_api/asyncio/api/application_integrations/__init__.py +5 -0
- sp_api/asyncio/api/application_integrations/application_integrations.py +119 -0
- sp_api/asyncio/api/application_management/__init__.py +5 -0
- sp_api/asyncio/api/application_management/application_management.py +36 -0
- sp_api/asyncio/api/authorization/__init__.py +5 -0
- sp_api/asyncio/api/authorization/authorization.py +54 -0
- sp_api/asyncio/api/catalog/__init__.py +5 -0
- sp_api/asyncio/api/catalog/catalog.py +111 -0
- sp_api/asyncio/api/catalog_items/__init__.py +6 -0
- sp_api/asyncio/api/catalog_items/catalog_items.py +93 -0
- sp_api/asyncio/api/clients/__init__.py +1 -0
- sp_api/asyncio/api/customer_feedback/__init__.py +5 -0
- sp_api/asyncio/api/customer_feedback/customer_feedback.py +111 -0
- sp_api/asyncio/api/data_kiosk/__init__.py +5 -0
- sp_api/asyncio/api/data_kiosk/data_kiosk.py +236 -0
- sp_api/asyncio/api/easy_ship/__init__.py +5 -0
- sp_api/asyncio/api/easy_ship/easy_ship.py +191 -0
- sp_api/asyncio/api/external_fulfillment/__init__.py +5 -0
- sp_api/asyncio/api/external_fulfillment/external_fulfillment.py +706 -0
- sp_api/asyncio/api/fba_inbound_eligibility/__init__.py +5 -0
- sp_api/asyncio/api/fba_inbound_eligibility/fba_inbound_eligibility.py +96 -0
- sp_api/asyncio/api/fba_small_and_light/__init__.py +5 -0
- sp_api/asyncio/api/fba_small_and_light/fba_small_and_light.py +213 -0
- sp_api/asyncio/api/feeds/feeds.py +260 -0
- sp_api/asyncio/api/finances/finances.py +100 -0
- sp_api/asyncio/api/fulfillment_inbound/fulfillment_inbound.py +1798 -0
- sp_api/asyncio/api/fulfillment_outbound/fulfillment_outbound.py +736 -0
- sp_api/asyncio/api/inventories/inventories.py +74 -0
- sp_api/asyncio/api/listings_items/__init__.py +0 -0
- sp_api/asyncio/api/listings_items/listings_items.py +170 -0
- sp_api/asyncio/api/listings_restrictions/__init__.py +0 -0
- sp_api/asyncio/api/listings_restrictions/listings_restrictions.py +36 -0
- sp_api/asyncio/api/merchant_fulfillment/__init__.py +0 -0
- sp_api/asyncio/api/merchant_fulfillment/merchant_fulfillment.py +384 -0
- sp_api/asyncio/api/messaging/__init__.py +0 -0
- sp_api/asyncio/api/messaging/messaging.py +511 -0
- sp_api/asyncio/api/models/__init__.py +4 -0
- sp_api/asyncio/api/notifications/__init__.py +0 -0
- sp_api/asyncio/api/notifications/notifications.py +295 -0
- sp_api/asyncio/api/orders/__init__.py +0 -0
- sp_api/asyncio/api/orders/orders.py +362 -0
- sp_api/asyncio/api/overrides/__init__.py +1 -0
- sp_api/asyncio/api/product_fees/__init__.py +0 -0
- sp_api/asyncio/api/product_fees/product_fees.py +194 -0
- sp_api/asyncio/api/product_type_definitions/__init__.py +0 -0
- sp_api/asyncio/api/product_type_definitions/product_type_definitions.py +75 -0
- sp_api/asyncio/api/products/__init__.py +0 -0
- sp_api/asyncio/api/products/products.py +405 -0
- sp_api/asyncio/api/products/products_definitions.py +11 -0
- sp_api/asyncio/api/replenishment/__init__.py +0 -0
- sp_api/asyncio/api/replenishment/replenishment.py +121 -0
- sp_api/asyncio/api/reports/__init__.py +0 -0
- sp_api/asyncio/api/reports/reports.py +439 -0
- sp_api/asyncio/api/sales/__init__.py +0 -0
- sp_api/asyncio/api/sales/sales.py +93 -0
- sp_api/asyncio/api/sellers/__init__.py +0 -0
- sp_api/asyncio/api/sellers/sellers.py +70 -0
- sp_api/asyncio/api/services/__init__.py +0 -0
- sp_api/asyncio/api/services/services.py +218 -0
- sp_api/asyncio/api/shipping/__init__.py +0 -0
- sp_api/asyncio/api/shipping/shipping.py +459 -0
- sp_api/asyncio/api/shipping/shippingV2.py +651 -0
- sp_api/asyncio/api/solicitations/__init__.py +0 -0
- sp_api/asyncio/api/solicitations/solicitations.py +78 -0
- sp_api/asyncio/api/supply_sources/__init__.py +0 -0
- sp_api/asyncio/api/supply_sources/supply_sources.py +138 -0
- sp_api/asyncio/api/tokens/__init__.py +0 -0
- sp_api/asyncio/api/tokens/tokens.py +65 -0
- sp_api/asyncio/api/upload/__init__.py +0 -0
- sp_api/asyncio/api/upload/upload.py +18 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_inventory/__init__.py +0 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_inventory/vendor_direct_fulfillment_inventory.py +64 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_orders/__init__.py +0 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_orders/vendor_direct_fulfillment_orders.py +196 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_payments/__init__.py +0 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_payments/vendor_direct_fulfillment_payments.py +254 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_shipping/__init__.py +0 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_shipping/vendor_direct_fulfillment_shipping.py +627 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_transactions/__init__.py +0 -0
- sp_api/asyncio/api/vendor_direct_fulfillment_transactions/vendor_direct_fulfillment_transactions.py +43 -0
- sp_api/asyncio/api/vendor_invoices/__init__.py +0 -0
- sp_api/asyncio/api/vendor_invoices/vendor_invoices.py +295 -0
- sp_api/asyncio/api/vendor_orders/__init__.py +0 -0
- sp_api/asyncio/api/vendor_orders/vendor_orders.py +210 -0
- sp_api/asyncio/api/vendor_shipments/__init__.py +0 -0
- sp_api/asyncio/api/vendor_shipments/vendor_shipments.py +118 -0
- sp_api/asyncio/api/vendor_transaction_status/__init__.py +0 -0
- sp_api/asyncio/api/vendor_transaction_status/vendor_transaction_status.py +41 -0
- sp_api/asyncio/auth/__init__.py +12 -0
- sp_api/asyncio/auth/access_token_client.py +145 -0
- sp_api/asyncio/auth/exceptions.py +5 -0
- sp_api/asyncio/base/__init__.py +53 -0
- sp_api/asyncio/base/_transport_httpx.py +50 -0
- sp_api/asyncio/base/base_client.py +8 -0
- sp_api/asyncio/base/client.py +169 -0
- sp_api/asyncio/util/__init__.py +29 -0
- sp_api/asyncio/util/key_maker.py +5 -0
- sp_api/asyncio/util/load_all_pages.py +55 -0
- sp_api/asyncio/util/load_date_bound.py +53 -0
- sp_api/asyncio/util/retry.py +88 -0
- sp_api/auth/_core.py +39 -0
- sp_api/auth/access_token_client.py +18 -29
- sp_api/base/ApiResponse.py +3 -2
- sp_api/base/_core.py +110 -0
- sp_api/base/_transport_httpx.py +39 -0
- sp_api/base/client.py +40 -63
- sp_api/base/helpers.py +1 -1
- sp_api/base/reportTypes.py +3 -2
- sp_api/util/__init__.py +36 -0
- sp_api/util/load_all_pages.py +2 -1
- sp_api/util/params.py +57 -0
- sp_api/util/product_fees.py +40 -0
- sp_api/util/products_definitions.py +169 -0
- sp_api/util/report_document.py +154 -0
- python_amazon_sp_api-1.9.18.dist-info/RECORD +0 -144
- tests/api/finances/test_finances.py +0 -19
- tests/api/notifications/test_notifications.py +0 -26
- tests/api/orders/test_orders.py +0 -122
- tests/api/product_fees/product_fees.py +0 -49
- tests/api/reports/test_reports.py +0 -127
- tests/client/test_auth.py +0 -59
- tests/client/test_base.py +0 -163
- tests/client/test_credential_provider.py +0 -45
- tests/client/test_helpers.py +0 -142
- {python_amazon_sp_api-1.9.18.dist-info → python_amazon_sp_api-2.0.7.dist-info/licenses}/LICENSE +0 -0
- {tests → sp_api/api/application_integrations}/__init__.py +0 -0
- {tests/api → sp_api/api/customer_feedback}/__init__.py +0 -0
- {tests/api/finances → sp_api/api/easy_ship}/__init__.py +0 -0
- {tests/api/notifications → sp_api/api/external_fulfillment}/__init__.py +0 -0
- {tests/api/orders → sp_api/asyncio}/__init__.py +0 -0
- {tests/api/product_fees → sp_api/asyncio/api/feeds}/__init__.py +0 -0
- {tests/api/reports → sp_api/asyncio/api/finances}/__init__.py +0 -0
- {tests/api/sellers → sp_api/asyncio/api/fulfillment_inbound}/__init__.py +0 -0
- {tests/client → sp_api/asyncio/api/fulfillment_outbound}/__init__.py +0 -0
- /tests/api/sellers/test_sellers.py → /sp_api/asyncio/api/inventories/__init__.py +0 -0
sp_api/api/feeds/feeds.py
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import zlib
|
|
2
2
|
|
|
3
|
-
import
|
|
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 =
|
|
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
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
245
|
+
with httpx.Client() as client:
|
|
246
|
+
doc_response = client.get(url)
|
|
244
247
|
|
|
245
248
|
encoding = (
|
|
246
249
|
doc_response.encoding
|
sp_api/api/finances/finances.py
CHANGED
|
@@ -1,10 +1,23 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
|
|
1
3
|
from sp_api.base import Client, Marketplaces, ApiResponse
|
|
2
4
|
from sp_api.base import sp_endpoint, fill_query_params
|
|
3
5
|
|
|
6
|
+
class FinancesVersion(str, enum.Enum):
|
|
7
|
+
V_0 = "v0"
|
|
8
|
+
V_2024_06_19 = "2024-06-19"
|
|
9
|
+
LATEST = "2024-06-19"
|
|
10
|
+
|
|
4
11
|
|
|
5
12
|
class Finances(Client):
|
|
13
|
+
version: FinancesVersion = FinancesVersion.V_0
|
|
14
|
+
|
|
15
|
+
def __init__(self, *args, **kwargs):
|
|
16
|
+
if "version" in kwargs:
|
|
17
|
+
self.version = kwargs.get("version", FinancesVersion.V_0)
|
|
18
|
+
super().__init__(*args, **{**kwargs, "version": self.version})
|
|
6
19
|
|
|
7
|
-
@sp_endpoint("/finances
|
|
20
|
+
@sp_endpoint("/finances/<version>/orders/{}/financialEvents")
|
|
8
21
|
def get_financial_events_for_order(self, order_id, **kwargs) -> ApiResponse:
|
|
9
22
|
"""
|
|
10
23
|
get_financial_events_for_order(self, order_id, **kwargs) -> ApiResponse
|
|
@@ -25,7 +38,7 @@ class Finances(Client):
|
|
|
25
38
|
fill_query_params(kwargs.pop("path"), order_id), params={**kwargs}
|
|
26
39
|
)
|
|
27
40
|
|
|
28
|
-
@sp_endpoint("/finances
|
|
41
|
+
@sp_endpoint("/finances/<version>/financialEvents")
|
|
29
42
|
def list_financial_events(self, **kwargs) -> ApiResponse:
|
|
30
43
|
"""
|
|
31
44
|
list_financial_events(self, **kwargs) -> ApiResponse:
|
|
@@ -39,7 +52,7 @@ class Finances(Client):
|
|
|
39
52
|
"""
|
|
40
53
|
return self._request(fill_query_params(kwargs.pop("path")), params={**kwargs})
|
|
41
54
|
|
|
42
|
-
@sp_endpoint("/finances
|
|
55
|
+
@sp_endpoint("/finances/<version>/financialEventGroups/{}/financialEvents")
|
|
43
56
|
def list_financial_events_by_group_id(
|
|
44
57
|
self, event_group_id, **kwargs
|
|
45
58
|
) -> ApiResponse:
|
|
@@ -58,7 +71,7 @@ class Finances(Client):
|
|
|
58
71
|
fill_query_params(kwargs.pop("path"), event_group_id), params={**kwargs}
|
|
59
72
|
)
|
|
60
73
|
|
|
61
|
-
@sp_endpoint("/finances
|
|
74
|
+
@sp_endpoint("/finances/<version>/financialEventGroups")
|
|
62
75
|
def list_financial_event_groups(self, **kwargs) -> ApiResponse:
|
|
63
76
|
"""
|
|
64
77
|
list_financial_event_groups(self, **kwargs) -> ApiResponse:
|
|
@@ -71,3 +84,16 @@ class Finances(Client):
|
|
|
71
84
|
|
|
72
85
|
"""
|
|
73
86
|
return self._request(kwargs.pop("path"), params={**kwargs})
|
|
87
|
+
|
|
88
|
+
@sp_endpoint("/finances/<version>/transactions")
|
|
89
|
+
def list_transactions(self, **kwargs) -> ApiResponse:
|
|
90
|
+
"""
|
|
91
|
+
list_transactions(self, **kwargs) -> ApiResponse:
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
**kwargs:
|
|
95
|
+
|
|
96
|
+
Returns: ApiResponse
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
return self._request(kwargs.pop("path"), params={**kwargs})
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
)
|
sp_api/api/orders/orders.py
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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 = [
|
|
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
|
sp_api/api/products/products.py
CHANGED
|
@@ -2,14 +2,19 @@ from typing import Optional, List, Dict, Union
|
|
|
2
2
|
|
|
3
3
|
from sp_api.base import ApiResponse, Client, fill_query_params, sp_endpoint
|
|
4
4
|
from sp_api.api.products.products_definitions import (
|
|
5
|
+
GetCompetitiveSummaryBatch,
|
|
6
|
+
GetFeaturedOfferExpectedPriceBatch,
|
|
5
7
|
GetItemOffersBatchRequest,
|
|
6
8
|
GetListingOffersBatchRequest,
|
|
7
9
|
)
|
|
10
|
+
from sp_api.util import ensure_csv
|
|
8
11
|
|
|
9
12
|
|
|
10
13
|
class Products(Client):
|
|
11
14
|
"""
|
|
12
|
-
:
|
|
15
|
+
:links:
|
|
16
|
+
https://github.com/amzn/selling-partner-api-docs/blob/main/references/product-pricing-api/productPricingV0.md
|
|
17
|
+
https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v2022-05-01-reference
|
|
13
18
|
"""
|
|
14
19
|
|
|
15
20
|
@sp_endpoint("/products/pricing/v0/price", method="GET")
|
|
@@ -300,11 +305,84 @@ class Products(Client):
|
|
|
300
305
|
add_marketplace=False,
|
|
301
306
|
)
|
|
302
307
|
|
|
308
|
+
@sp_endpoint('/batches/products/pricing/2022-05-01/offer/featuredOfferExpectedPrice', method='POST')
|
|
309
|
+
def get_featured_offer_expected_price_batch(self, requests_: Optional[
|
|
310
|
+
Union[List[Dict], GetFeaturedOfferExpectedPriceBatch]], **kwargs) -> ApiResponse:
|
|
311
|
+
"""
|
|
312
|
+
get_featured_offer_expected_price_batch(self, **kwargs) -> ApiResponse
|
|
313
|
+
|
|
314
|
+
Returns the set of responses that correspond to the batched list of up to 40 requests defined in the request
|
|
315
|
+
body. The response for each successful (HTTP status code 200) request in the set includes the computed listing
|
|
316
|
+
price at or below which a seller can expect to become the featured offer (before applicable promotions).
|
|
317
|
+
This is called the featured offer expected price (FOEP). Featured offer is not guaranteed, because competing
|
|
318
|
+
offers may change, and different offers may be featured based on other factors, including fulfillment
|
|
319
|
+
capabilities to a specific customer. The response to an unsuccessful request includes the available error text.
|
|
320
|
+
|
|
321
|
+
**Usage Plan:**
|
|
322
|
+
|
|
323
|
+
====================================== ==============
|
|
324
|
+
Rate (requests per second) Burst
|
|
325
|
+
====================================== ==============
|
|
326
|
+
.033 1
|
|
327
|
+
====================================== ==============
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
requests_: [dict] The request associated with the getFeaturedOfferExpectedPriceBatch API call.
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
ApiResponse:
|
|
334
|
+
"""
|
|
335
|
+
if isinstance(requests_, GetFeaturedOfferExpectedPriceBatch):
|
|
336
|
+
get_featured_offer_expected_price_batch_request = requests_.to_dict()
|
|
337
|
+
else:
|
|
338
|
+
get_featured_offer_expected_price_batch_request = {"requests": requests_}
|
|
339
|
+
|
|
340
|
+
return self._request(
|
|
341
|
+
kwargs.pop('path'),
|
|
342
|
+
data=get_featured_offer_expected_price_batch_request,
|
|
343
|
+
params={**kwargs},
|
|
344
|
+
add_marketplace=False
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
@sp_endpoint('/batches/products/pricing/2022-05-01/items/competitiveSummary', method='POST')
|
|
348
|
+
def get_competitive_summary_batch(self, requests_: Optional[Union[List[Dict], GetCompetitiveSummaryBatch]], **kwargs) -> ApiResponse:
|
|
349
|
+
"""
|
|
350
|
+
get_competitive_summary(self, **kwargs) -> ApiResponse
|
|
351
|
+
|
|
352
|
+
Returns the competitive summary response including featured buying options for the ASIN and `marketplaceId` combination.
|
|
353
|
+
|
|
354
|
+
**Usage Plan:**
|
|
355
|
+
|
|
356
|
+
====================================== ==============
|
|
357
|
+
Rate (requests per second) Burst
|
|
358
|
+
====================================== ==============
|
|
359
|
+
.033 1
|
|
360
|
+
====================================== ==============
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
requests_: The request associated with the getCompetitiveSummary API call.
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
ApiResponse:
|
|
367
|
+
"""
|
|
368
|
+
if isinstance(requests_, GetCompetitiveSummaryBatch):
|
|
369
|
+
get_competitive_summary_batch_request = requests_.to_dict()
|
|
370
|
+
else:
|
|
371
|
+
get_competitive_summary_batch_request = {"requests": requests_}
|
|
372
|
+
|
|
373
|
+
return self._request(
|
|
374
|
+
kwargs.pop('path'),
|
|
375
|
+
data=get_competitive_summary_batch_request,
|
|
376
|
+
params={**kwargs},
|
|
377
|
+
add_marketplace=False
|
|
378
|
+
)
|
|
379
|
+
|
|
303
380
|
def _create_get_pricing_request(self, item_list, item_type, **kwargs):
|
|
381
|
+
items_csv = ensure_csv(item_list)
|
|
304
382
|
return self._request(
|
|
305
383
|
kwargs.pop("path"),
|
|
306
384
|
params={
|
|
307
|
-
**{f"{item_type}s":
|
|
385
|
+
**{f"{item_type}s": items_csv},
|
|
308
386
|
"ItemType": item_type,
|
|
309
387
|
**(
|
|
310
388
|
{"ItemCondition": kwargs.pop("ItemCondition")}
|
|
@@ -1,85 +1,11 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
MarketplaceId: str
|
|
13
|
-
ItemCondition: str = None
|
|
14
|
-
CustomerType: str = None
|
|
15
|
-
headers: Dict = None
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
@dataclass
|
|
19
|
-
class GetItemOffersBatchRequest:
|
|
20
|
-
"""Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference
|
|
21
|
-
#getitemoffersbatchrequest"""
|
|
22
|
-
|
|
23
|
-
requests: Optional[List[Union[ItemOffersRequest, Dict]]] = None
|
|
24
|
-
|
|
25
|
-
def __post_init__(self):
|
|
26
|
-
self.requests = self.parse_requests(self.requests)
|
|
27
|
-
|
|
28
|
-
def to_dict(self):
|
|
29
|
-
return asdict(self)
|
|
30
|
-
|
|
31
|
-
@staticmethod
|
|
32
|
-
def parse_requests(requests) -> List[ItemOffersRequest]:
|
|
33
|
-
parsed_requestes = []
|
|
34
|
-
|
|
35
|
-
for request in requests:
|
|
36
|
-
if isinstance(request, Dict):
|
|
37
|
-
request = ItemOffersRequest(**request)
|
|
38
|
-
|
|
39
|
-
if not isinstance(request, ItemOffersRequest):
|
|
40
|
-
raise TypeError
|
|
41
|
-
|
|
42
|
-
parsed_requestes.append(request)
|
|
43
|
-
|
|
44
|
-
return parsed_requestes
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
@dataclass
|
|
48
|
-
class ListingOffersRequest:
|
|
49
|
-
"""Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference
|
|
50
|
-
#listingoffersrequest"""
|
|
51
|
-
|
|
52
|
-
uri: str
|
|
53
|
-
MarketplaceId: str
|
|
54
|
-
ItemCondition: str
|
|
55
|
-
method: str = "GET"
|
|
56
|
-
CustomerType: str = "Consumer"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
@dataclass
|
|
60
|
-
class GetListingOffersBatchRequest:
|
|
61
|
-
"""Implements definition: https://developer-docs.amazon.com/sp-api/docs/product-pricing-api-v0-reference
|
|
62
|
-
#getlistingoffersbatchrequest"""
|
|
63
|
-
|
|
64
|
-
requests: Optional[List[Union[ListingOffersRequest, Dict]]] = None
|
|
65
|
-
|
|
66
|
-
def __post_init__(self):
|
|
67
|
-
self.requests = self.parse_requests(self.requests)
|
|
68
|
-
|
|
69
|
-
def to_dict(self):
|
|
70
|
-
return asdict(self)
|
|
71
|
-
|
|
72
|
-
@staticmethod
|
|
73
|
-
def parse_requests(requests) -> List[ListingOffersRequest]:
|
|
74
|
-
parsed_requestes = []
|
|
75
|
-
|
|
76
|
-
for request in requests:
|
|
77
|
-
if isinstance(request, Dict):
|
|
78
|
-
request = ListingOffersRequest(**request)
|
|
79
|
-
|
|
80
|
-
if not isinstance(request, ListingOffersRequest):
|
|
81
|
-
raise TypeError
|
|
82
|
-
|
|
83
|
-
parsed_requestes.append(request)
|
|
84
|
-
|
|
85
|
-
return parsed_requestes
|
|
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
|
+
)
|