python-amazon-mws¶
python-amazon-mws is a Python connector to Amazon Marketplace Web Services (or MWS). It provides a simple way to build and send requests to MWS, allowing access to all that MWS can do from your Python application.
Use Feeds to update your product listings, run Reports, get updates on your Orders, create and manage FBA Inbound Shipments… do it all with python-amazon-mws!
Note
This is a third-party connector with no direct affiliation to Amazon.
CHANGELOG¶
v1.0dev16¶
Note
This is a prerelease version for v1.0.
- Date
November 2020
- Issues
This update focused on the InboundShipments API, adding some new ways to input and manage data related to FBA shipments while also introducing some comprehensive documentation of the same.
Also includes the Products API’s get_my_fees_estimate method, deprecation warnings for old argument names to smooth the transition from v0.8.
Major changes¶
Products API
get_my_fees_estimate
method added.See #216 for details.
Deprecation warnings for old argument names.
Some argument names for certain requests had changed between v0.8 and v1.0dev. This change makes it possible to use the v0.8 argument names in current code.
When using an old argument name, the method will raise a deprecation warning, indicating those old argument names will be removed in v1.1. The method will then proceed as expected using the correct arg names.
See #222 for details.
Datatype models added for InboundShipments.
All models for this API can be found in module
mws.models.inbound_shipments
.Added datatype models for
Address
,PrepDetails <mws.InboundShipments.PrepDetails
,InboundShipmentPlanRequestItem <mws.InboundShipments.InboundShipmentPlanRequestItem
, andInboundShipmentItem <mws.InboundShipments.InboundShipmentItem
. These models can be used in relevant arguments for request methods related to FBA shipment creation and updating (create_inbound_shipment_plan
,create_inbound_shipment
, andupdate_inbound_shipment
.With this addition, it is now possible to include
PrepDetails
for items being added to shipments. This was not possible using the now-“legacy” item dictionary method (though it is still possible using the lower-level generic requests).
Added
shipment_items_from_plan
helper method.The method can process the contents of a shipment plan from the parsed response from
create_inbound_shipment_plan
, turning the returned items into a set ofInboundShipmentItem
models automatically.
New documentation for Managing FBA Shipments added.
Comprehensive documentation for how to manage FBA shipments using the InboundShipments API.
Showcases the usage of new models provided by this update.
Minor changes¶
Links to Amazon MWS documentation throughout the code base updated from http:// to https://.
Type annotations added to request methods for InboundShipments API. - As part of this, certain assert-style checks for argument types have been removed.
Tests for InboundShipments request methods overhauled, removing dependency on unittest in favor of pytest.
URL naming improvements for documentation pages, and proper usage of doc links instead of adding extraneous anchor links. - Some bookmarks may break with this change, apologies!
Dev update callout removed from project README.
Development tooling configurations moved into setup.cfg for consistency.
Project test suite expanded to Python 3.9 and Ubuntu-20.04 - All automated testing is already performed in a matrix strategy, across Python 3.6, 3.7, 3.8, and 3.9; and on OSes Windows, MacOS, Ubuntu-18, and Ubuntu-20. Every combination of all these versions and OSes is tested.
v1.0dev15¶
Note
This is a prerelease version for v1.0.
- Date
September 2020
This update represents a major step towards a v1.0 release candidate. Much of the core components of the project have been restructured, new XML parsing logic has been added, and API code has been streamlined to ease development efforts going forward.
Major changes¶
Added dependency
xmltodict
for parsing XML documents to Python dict objects.Added
MWSResponse
, intended to replaceDictWrapper
andDataWrapper
response wrappers; andDotDict
, intended to replaceObjectDict
.These features are in preview mode. See 1 .
Added
MWS.generic_request()
, a low-level interface for sending requests to any MWS operation with any set of parameters necessary (using new utility function,mws.utils.params.flat_dict_param
).Several objects have been moved, renamed, and/or retooled to improve code structuring and interoperability, most notably
mws.utils
(which has been broken down to multiple modules with different concerns).
Code restructuring¶
Several objects have been moved and/or renamed, with new modules added to contain them. At the same time, the namespace for most of those objects has been left mostly intact. Following changes relate to objects whose imports may need to be adjusted in application code.
mws.utils
, formerly a single module file, is now a directory containing other modules with separated concerns.Moved
mws.mws.DictWrapper
tomws.utils.DictWrapper
.Moved
mws.mws.DataWrapper
tomws.utils.DataWrapper
.Moved
mws.mws.ObjectDict
tomws.utils.ObjectDict
.Moved
mws.mws.XML2Dict
tomws.utils.XML2Dict
.Moved/renamed
mws.mws.clean_params
tomws.utils.clean_params_dict
.“Cleaning” logic has been broken down further with
mws.utils.params.clean_value
, which passes to other “clean_FOO” methods such asclean_string
,clean_bool
, andclean_date
.
Changed
mws.utils.get_utc_timestamp
tomws.utils.mws_utc_now
.get_utc_timestamp
returned an ISO-8601-formatted string of the current datetime in UTC timezone.mws_utc_now
produces the same datetime, but instead returns adatetime.datetime
object. An ISO-8601 formatted string can easily be obtained using the.isoformat()
method.
Changed
mws.mws.remove_namespace
tomws.utils.remove_xml_namespaces
.The new version works the same as the old, but can now accept bytes as well as strings.
Deprecations¶
The following have been deprecated:
DictWrapper
(removed in v1.1), replaced byMWSResponse
in v1.0 (currently in preview mode).DataWrapper
(removed in v1.1), replaced byMWSResponse
in v1.0 (currently in preview mode).ObjectDict
(removed in v1.1), replaced byDotDict
in v1.0 (currently in preview mode).XML2Dict
(removed in v1.1). XML parsing into Python objects will be performed by thexmltodict
library starting in v1.0.MWS.enumerate_param
(removed in v1.0). Use utility methods found inmws.utils.params
, instead.
Minor changes¶
New arguments are available when instantiating an API class (subclasses of the
MWS
main class, such asFeeds
andOrders
):Argument and class attr
user_agent_str
sets the User Agent String sent with requests to MWS. This can be used to override PAM’s default agent string,"python-amazon-mws/{version} (Language=Python)"
.Argument
headers
and attributeextra_headers
accepts a dictionary with headers to add to each request, if necessary. Headers can still be altered per-request by passing anextra_headers
kwarg tomake_request
orgeneric_request
.Argument and class attr
force_response_encoding
allows specifying the encoding used to decode a response’s bytes content, when parsed byMWSResponse
into aDotDict
.Amazon documentation states they use ISO-8859-1 (aka Latin-1) encoding. However, some responses may still be encoded differently, such as in UTF-8, even if this behaviour is not well-documented. By default, python-amazon-mws relies on
requests.Response.apparent_encoding
to guess the character set to decode, which should be sufficient for most uses.Setting
force_response_encoding='utf-8'
, for example, will force responses to be decoded as UTF-8 automatically for any request made with that API class instance.Encoding can also be adjusted on the
MWSResponse
object, by assigningresponse.encoding = 'utf-8'
and then callingresponse.parse_response()
to re-parse content.
All request methods are now required to pass the
Action
name of an MWS operation as the first argument toMWS.make_request
orMWS.generic_request
. Previously, this was expected as a parameter in the data sent with a request.MWS.make_request
argumentextra_data
has been renamed toparams
, and can now default toNone
. This permits operations such asGetServiceStatus
, which require no parameters, to pass without issue.The
timeout
kwarg inMWS.make_request
has been promoted to a named argument, with a default value of 300 seconds.
Footnotes
- 1
1.0dev15 features preview: Prior to v1.0,
DictWrapper
andDataWrapper
will still be used as default response wrappers for all requests; and the.parsed
interface for these objects will continue to beObjectDict
instances.To use
MWSResponse
andDotDict
for response parsing in development versions (1.0dev15 and up), you must enable the_use_feature_mwsresponse
feature flag:Instantiate an API class, i.e.
feeds_api = Feeds(...)
.Set flag
_use_feature_mwsresponse
toTrue
on the class instance:feeds_api._use_feature_mwsresponse = True
.
Now all requests made through this class instance will return responses as
MWSResponse
.
Prerequisites for MWS connectivity¶
See also
All links in this documentation point to the developer.amazonservices.com
domain, but other regional domains are provided by Amazon. For a list of portals for other
regions, please see Related Resources (MWS documentation link).
In order to use python-amazon-mws, you must have an Amazon Professional Seller account, and you must register as a developer. You will then be provided a set of MWS credentials, which include your Seller ID, Access Key, and Secret Key (and, possibly, Auth Token).
These credentials, along with a Marketplace ID, will be needed to make requests to MWS, whether using python-amazon-mws or any other MWS-related service.
Test MWS access using Scratchpad¶
You can test your access to MWS using Amazon MWS Scratchpad (docs):
Open the Scratchpad.
Warning
Always verify the URL of the Scratchpad before entering your MWS credentials! The domain should be
mws.amazonservices.com
or one of Amazon’s other regional domains (see here for a list of regional portals).Enter your MWS credentials in the Authentication section.
In API Section, choose “Products”.
In Operation, choose “ListMatchingProducts”.
Under Required API Parameters, enter:
MarketplaceID
: A valid MarketplaceID for your desired marketplace (example:ATVPDKIKX0DER
for the US market). See: Amazon MWS endpoints and MarketplaceId values.Query
:python
, to search for products containing “python” somewhere in their description.
Click Submit.
If your access works, you should an XML response beginning with ListMatchingProductsResponse
.
Otherwise, you may see an ErrorResponse
, with an error message indicating the problem.
Installation¶
Currently, two versions of the package are available: an older v0.8.x, available on PyPI; and the in-development v1.0devXY, available on GitHub.
For new projects, we recommend using v1.0devXY, as it contains a more complete set of API sections and operations. Note that this version is still pre-alpha, so some parts of the package are subject to change as we slowly update from the original 0.8.x code.
Use pip
to install 1.0devXY from GitHub off the develop
branch:
pip install git+https://github.com/python-amazon-mws/python-amazon-mws.git@develop#egg=mws
Getting started¶
Note
We assume you have an Amazon Professional Seller account and developer access to be able to use MWS. If not, please see Prerequisites for MWS connectivity.
Entering credentials¶
To begin, use your MWS Credentials to instantiate one of the API classes.
We will use the Products
API for this example.
Where you store these credentials is up to you, but we recommend using environment variables, like so:
import os
from mws import Products
products_api = Products(
access_key=os.environ["MWS_ACCESS_KEY"],
secret_key=os.environ["MWS_SECRET_KEY"],
account_id=os.environ["MWS_ACCOUNT_ID"],
auth_token=os.environ["MWS_AUTH_TOKEN"],
)
# `auth_token` is optional, depending on how you your MWS access is set up.
Making requests¶
Each API class contains a number of request methods, which closely match the Operations available to that API section in MWS. You should refer to MWS documentation for the API class you intend to use and provide the data specified by that operation.
For our example, we will use the Products API
operation ListMatchingProducts.
In python-amazon-mws, this is done using an instance of the Products
API class and its method
list_matching_products
:
from mws import Marketplaces
# Marketplaces is an enum we can use to fill in the `marketplace_id` value,
# instead of needing to manually enter, i.e., "ATVPDKIKX0DER"
my_marketplace = Marketplaces.US.marketplace_id
response = products_api.list_matching_products(
marketplace_id=my_marketplace,
query="python",
)
The request is sent automatically when list_matching_products
is called, and a
response
is returned. MWS typically returns an XML document encoded in ISO-8859-1
(per Amazon’s standards),
which python-amazon-mws attempts to decode automatically.
For most responses (including our example list_matching_products
), the response
will be a
DictWrapper
object containing:
response.original
, the original XML document;response.response
, the HTTP response code of the request (200, 400, etc.); andresponse.parsed
, a parsed version of the XML tree. (See Using Parsed XML Responses).
Certain responses (such as the GetReport operation, under
the Reports API) may return other content types, such as PDFs, tab-delimited flat files, ZIP files,
and so on. Non-XML responses will be wrapped in a DataWrapper
object with similar attributes
as DictWrapper
, with the raw document stored in .original
, and .parsed
simply returning
.original
for convenience.
Warning
New in version 1.0dev15.
DictWrapper
and DataWrapper
are deprecated, and will be removed in v1.1. During development testing,
these objects will still be returned from requests by default, and parsed content will still use ObjectDict
instances (also deprecated).
To use newer features, such as the MWSResponse
wrapper and
parsed XML using DotDict
, set flag _use_feature_mwsresponse
to
True
on an API class instance before making any requests:
# instantiate your class
products_api = Products(...)
# set the new feature flag
products_api._use_feature_mwsresponse = True
# run your requests as normal
response = products_api.list_matching_products(...)
For details on using these newer features, please see:
MWSResponse
and DotDict
will become the default objects returned by requests in v1.0.
Generic Requests¶
New in version 1.0dev15: Generic request support added.
While most MWS operations are well-covered by python-amazon-mws with dedicated and purpose-built request methods, Amazon may occasionally update MWS to include new parameters that we do not yet provide access to. Either that, or you just want lower-level access to input your own request, without going through the rest of python-amazon-mws to do so.
For these situations, you can use APIClass.generic_request()
, available
in all API classes that inherit from the base MWS
class.
Back to basics¶
To use .generic_request()
, you must first instantiate the API class that contains the operation you want to send.
Using the correct API class is required, as the base URI used the build the request is different for each API section.
For instance, to use the ListOrders
operation in the Orders
API, you would create an
Orders
instance.
With the class instantiated, specify the operation to call as the action
arg to .generic_request()
;
then provide a dict of parameters for your request as params
:
import datetime
from mws import Orders, Marketplaces
my_marketplace_ids = [
Marketplaces.US.marketplace_id,
Marketplaces.UK.marketplace_id,
]
orders_api = Orders(MY_ACCESS_KEY, MY_SECRET_KEY, MY_ACCOUNT_ID)
response = orders_api.generic_request(
action="ListOrders",
params={
"MarketplaceId.Id": my_marketplace_ids,
"CreatedAfter": datetime.datetime(2020, 8, 28),
}
)
The above is equivalent to calling
Orders.list_orders
with:
response = orders_api.list_orders(
marketplace_ids=my_marketplace_ids,
created_after=datetime.datetime(2020, 8, 28),
)
Key differences between a generic request and the “pythonic” version include:
The
action
must be specified for each call, using the case-sensitive name of the MWS operation (usually in CapCase with no underscores).params
must include case-sensitive keys matching the parameters required for the MWS operation, according to Amazon documentation.The
params
dict is flattened, such that nested lists and dicts inparams
are keyed and enumerated into appropriate request parameter keys.
Parameter dict flattening¶
Generic requests make use of flat_param_dict()
to convert nested
Mappings and Iterables into a “flat” set of key-value pairs.
Rules
Nested mapping objects (
dict
,DotDict
, etc.) are recursively flattened, joining the keys of the child mapping to the parent key with.
.Nested iterables (
list
,tuple
,set
, etc.) are enumerated with a 1-based index, with each index joined to the parent key with.
.All nested mappings and iterables are processed recursively, flattening other mappings and iterables along the way.
Example
value = {
"a": 1,
"b": "hello",
"c": [
"foo",
"bar",
{
"spam": "ham",
"eggs": [
5,
6,
7,
],
},
],
}
The above, when passed through flat_param_dict()
, produces:
{
"a": 1,
"b": "hello",
"c.1": "foo",
"c.2": "bar",
"c.3.spam": "ham",
"c.3.eggs.1": 5,
"c.3.eggs.2": 6,
"c.3.eggs.3": 7,
}
“a” and “b” keys point to non-dict, non-sequence values (not including strings), so they return their original values.
“c” contains an iterable (list), which is enumerated with a 1-based index. Each index is concatenated to “c” with “.”, creating keys “c.1” and “c.2”.
At “c.3”, another nested object was found. This is processed recursively, and each key of the resulting dict is concatenated to the parent “c.3” to create multiple keys in the final output.
The same occurs for “c.3.eggs”, where an iterable is found and is enumerated.
The final output should always be a flat dictionary with key-value pairs.
Using a prefix
flat_param_dict
accepts a prefix
argument, used mainly when flattening nested objects recursively.
When provided, all keys in the resulting output will begin with prefix + '.'
:
# Using the same `value` as before:
flat_param_dict(value, prefix="example")
# Produces:
{
"example.a": 1,
"example.b": "hello",
"example.c.1": "foo",
"example.c.2": "bar",
"example.c.3.spam": "ham",
"example.c.3.eggs.1": 5,
"example.c.3.eggs.2": 6,
"example.c.3.eggs.3": 7,
}
Generic request component methods¶
-
MWS.
generic_request
(action, params=None, method='POST', timeout=300, **kwargs)[source]¶ Builds a generic request with arbitrary parameter arguments. This method should be called from an API subclass (
Orders
,Feeds
, etc.), else theuri
attribute of the class instance must be set manually.This method’s signature matches that of
.make_request
, as the two methods are similar. However,params
is expected to be either the defaultNone
or a nested dictionary, that is then passed toflat_param_dict()
.
-
mws.utils.params.
flat_param_dict
(value, prefix='')[source]¶ Returns a flattened params dictionary by collapsing nested dicts and non-string iterables.
Any arbitrarily-nested dict or iterable will be expanded and flattened.
Each key in a child dict will be concatenated to its parent key.
Elements of a non-string iterable will be enumerated using a 1-based index, with the index number concatenated to the parent key.
In both cases, keys and sub-keys are joined by
.
.
If
prefix
is set, all keys in the resulting output will begin withprefix + '.'
.- Parameters
value (Union[str, collections.abc.Mapping, List]) –
prefix (str) –
- Return type
dict
Managing Fulfillment Inbound (FBA) Shipments¶
Warning
The following includes features added in v1.0dev16 related to Datatype models.
Models can be called from the API class that uses them. For example, to use the
Address
model attached to the
InboundShipments
API:
from mws import InboundShipments
# from the class itself:
my_address = InboundShipments.Address(...)
# or from an instance of the class:
inbound_shipments_api = InboundShipments(...)
my_address = inbound_shipments_api.Address(...)
Note
Examples in this document use MWSResponse preview features.
MWS handles Fulfillment Inbound Shipments, also known as FBA (for “Fulfillment By Amazon”) through the Fulfillment Inbound Shipment API section. Users should familiarize themselves with this section of the API in MWS documentation before getting started.
In python-amazon-mws, this API is covered by InboundShipments
.
Basic steps to create a shipment in MWS¶
For a quick overview, MWS requires the following pattern to creating FBA shipments:
Send a request to
create_inbound_shipment_plan
with all items you wish to ship, along with their quantities, conditions, prep details, and so on.MWS will respond with one or more shipment plans, indicating where to send each of your items. Multiple shipments may be requested, and the same item may have its quantities split between these shipments. Each plan also returns the FBA Shipment ID needed to create a shipment, as well as the ID and address of the Fulfillment Center that will expect that shipment.
For each shipment plan, send a
create_inbound_shipment
request with the items, quantities, and other details identified in the plan.Optionally, it is possible to use
update_inbound_shipment
to add planned items for a new shipment to an existing shipment under certain conditions. Using this option improperly may violate the terms of your seller account, so use with caution!
We’ll look at each of these steps in detail below.
Warning
MWS does not provide a sandbox for testing functionality. If you use examples from this guide for testing purposes, you will need to use live data to do it, and will be creating real FBA shipments. Please use this guide at your own risk.
Some things to keep in mind when testing this functionality:
Make note of any Shipment IDs for shipments you generate with these examples.
Use custom shipment names to help identify test shipments, such as “TEST_IGNORE”, so you can more easily find those shipments in Seller Central, if you lose track of them in testing.
Inform other members of your organization that you are conducting tests, particularly if they use Seller Central or other MWS-related tooling to check on shipment statuses.
Leaving test shipments in WORKING or SHIPPED statuses may have an impact on your product inventory. We advise changing these to CANCELLED when you complete your testing.
Requesting a shipment plan¶
We start by informing Amazon we have items we wish to ship, requesting a shipment plan through MWS.
You will need:
MWS credentials to authenticate with MWS (not in scope for these docs).
A valid ship-from address, presumably the address of the facility where you will be shipping items from.
A list of Seller SKUs for items in your product catalog to add to new shipments.
Create the API instance¶
To begin, create an instance of InboundShipments
as you would any other API class in python-amazon-mws.
You will then use this API class instance to initiate requests to MWS.
from mws import InboundShipments
# assuming MWS credentials are stored in environment variables (your setup may vary):
inbound_api = InboundShipments(
access_key=os.environ("MWS_ACCESS_KEY"),
secret_key=os.environ("MWS_SECRET_KEY"),
account_id=os.environ("MWS_ACCOUNT_ID"),
)
Create your ship-from address¶
Next, set up your ship-from address, which is required for the three core operations related to FBA shipments: planning, creation, and updating.
The simplest way to store your ship-from address is to create an instance of the
Address
model:
my_address = inbound_api.Address(
name="My Warehouse",
address_line_1="555 Selling Stuff Lane",
address_line_2="Suite 404",
city="New York",
district_or_county="Brooklyn",
state_or_province_code="NY",
country_code="US",
postal_code="11265",
)
This model closely follows the structure of MWS’s Datatype of the same name. You should refer to MWS documentation for this Datatype to ensure all necessary elements of your address are included.
Note
If you’re curious, you can use any model’s .to_params()
method to return a dictionary containing the
request parameters of that model and their values.
my_address.to_params()
# {'Name': 'My Warehouse', 'AddressLine1': '555 Selling Stuff Lane', 'AddressLine2': 'Suite 404', 'City': 'New York', 'DistrictOrCounty': 'Brooklyn', 'StateOrProvinceCode': 'NY', 'CountryCode': 'US', 'PostalCode': '11265'}
This method also accepts a prefix
argument, which adds the prefix string plus '.'
before each parameter key:
my_address.to_params("ShipFromAddress")
# {'ShipFromAddress.Name': 'My Warehouse', 'ShipFromAddress.AddressLine1': '555 Selling Stuff Lane', 'ShipFromAddress.AddressLine2': 'Suite 404', 'ShipFromAddress.City': 'New York', 'ShipFromAddress.DistrictOrCounty': 'Brooklyn', 'ShipFromAddress.StateOrProvinceCode': 'NY', 'ShipFromAddress.CountryCode': 'US', 'ShipFromAddress.PostalCode': '11265'}
Using .to_params()
in your own code is usually not necessary, as most request methods will convert the
model instance to parameters automatically.
Optional: Store your ship-from address on the API instance¶
If you plan to make several requests in a row related to the same ship-from address, you can store the address on
an instance of InboundShipments
API as .from_address
:
inbound_api.from_address = my_address
When using this option, you can omit passing from_address=my_address
as an argument in the request examples below.
All relevant request methods (create_inbound_shipment_plan
, create_inbound_shipment
, and
update_inbound_shipment
) will pass the stored from_address
to these requests automatically.
In any case, supplying a from_address
argument to one of these methods will be used as an override, regardless of
the address stored within the API instance.
Request a shipment plan¶
Amazon’s workflow for creating a shipment uses the following pattern:
Create a shipment plan by sending a
CreateInboundShipmentPlan
request. This informs Amazon which items you intend to ship and the total quantity for each, as well as any prep details, item conditions, and so on.MWS responds with one or more planned shipments for those items. They may request certain items are sent to certain fulfillment centers, and may even split quantities for some items to multiple facilities. You must use the planned shipments to create your actual shipments.
Send a
CreateInboundShipment
request for each planned shipment. This should include the ShipmentId, DestinationFulfillmentCenterId, and any items and quantities returned in the response fromCreateInboundShipmentPlan
, so that the new shipment matches the planned one.A successful request to
CreateInboundShipment
will create an FBA Shipment, which you can further interact with through MWS or on Seller Central.
We’ll start by creating the shipment plan, for which we need a list of items.
Building a list of planned items¶
Each item in your shipment plan can be represented by an instance of
InboundShipmentPlanRequestItem
,
which closely follows the MWS Datatype of the same name:
item1 = inbound_api.InboundShipmentPlanRequestItem('MY-SKU-1', 36)
item2 = inbound_api.InboundShipmentPlanRequestItem('MY-SKU-2', 12)
my_items = [item1, item2]
The only required arguments for the model are sku
and quantity
, which are sufficient for loose item
shipments of new items when prep details do not need to be specified.
Note
You can add more detail to an InboundShipmentPlanRequestItem
instance, depending on your needs.
If you were sending, for example, an item that comes in case-packs of 12, in NewOEM condition, with a particular
ASIN, and requires Amazon to prep each item with Polybagging; you might create that item model like so:
my_condition = inbound_api.ItemCondition.NEW_OEM # or the string "NewOEM"
my_prep_details = inbound_api.PrepDetails(
prep_instruction=PrepInstruction.POLYBAGGING, # or "Polybagging"
prep_owner=PrepDetails.AMAZON # or "AMAZON"
)
detailed_item = inbound_api.InboundShipmentPlanRequestItem(
sku='MY-OTHER-SKU',
quantity=48,
quantity_in_case=12,
asin='B0123456789',
condition=my_condition,
prep_details_list=[my_prep_details],
)
Again for the curious, detailed_item.to_params()
looks like so:
detailed_item.to_params()
# {'SellerSKU': 'MY-OTHER-SKU', 'ASIN': 'B0123456789', 'Condition': 'NewOEM', 'Quantity': 48, 'QuantityInCase': 12, 'PrepDetailsList.member.1.PrepInstruction': 'Polybagging', 'PrepDetailsList.member.1.PrepOwner': 'AMAZON'}
Sending the request¶
Now that we have our items handy, it’s time to make our request for a shipment plan:
# using `inbound_api`, `my_address` and `my_items` from previous examples
resp = inbound_api.create_inbound_shipment_plan(my_items, from_address=my_address)
Other arguments you can provide include:
country_code
orsubdivision_code
, the country or country subdivision you are planning to send a shipment to.country_code
defaults to"US"
;subdivision_code
(which refers to a subdivision of India specifically) defaults toNone
.According to MWS documentation, providing both options will return an error.
label_preference
, a preference for label preparation. Defaults toNone
, which MWS may interpret as “SELLER_LABEL” internally.
And note that the from_address
argument is optional if the address has been
stored on the API instance.
Processing shipment plans¶
If our request to create shipment plans was successful, MWS will respond with an XML document containing plan details.
python-amazon-mws will automatically parse this response, giving us access to the
Python representation of the response in resp.parsed
.
For reference, we will use the following example XML response from create_inbound_shipment_plan
. You can access
this document in your own response by checking resp.original.text
:
<?xml version="1.0"?>
<CreateInboundShipmentPlanResponse
xmlns="http://mws.amazonaws.com/FulfillmentInboundShipment/2010-10-01/">
<CreateInboundShipmentPlanResult>
<InboundShipmentPlans>
<member>
<DestinationFulfillmentCenterId>ABE2</DestinationFulfillmentCenterId>
<LabelPrepType>SELLER_LABEL</LabelPrepType>
<ShipToAddress>
<City>Breinigsville</City>
<CountryCode>US</CountryCode>
<PostalCode>18031</PostalCode>
<Name>Amazon.com</Name>
<AddressLine1>705 Boulder Drive</AddressLine1>
<StateOrProvinceCode>PA</StateOrProvinceCode>
</ShipToAddress>
<EstimatedBoxContentsFee>
<TotalUnits>10</TotalUnits>
<FeePerUnit>
<CurrencyCode>USD</CurrencyCode>
<Value>0.10</Value>
</FeePerUnit>
<TotalFee>
<CurrencyCode>USD</CurrencyCode>
<Value>10.0</Value>
</TotalFee>
</EstimatedBoxContentsFee>
<Items>
<member>
<FulfillmentNetworkSKU>FNSKU00001</FulfillmentNetworkSKU>
<Quantity>1</Quantity>
<SellerSKU>SKU00001</SellerSKU>
<PrepDetailsList>
<PrepDetails>
<PrepInstruction>Taping</PrepInstruction>
<PrepOwner>AMAZON</PrepOwner>
</PrepDetails>
</PrepDetailsList>
</member>
<member>
...
</member>
</Items>
<ShipmentId>FBA0000001</ShipmentId>
</member>
<member>
...
</member>
</InboundShipmentPlans>
</CreateInboundShipmentPlanResult>
<ResponseMetadata>
<RequestId>babd156d-8b2f-40b1-a770-d117f9ccafef</RequestId>
</ResponseMetadata>
</CreateInboundShipmentPlanResponse>
Gathering shipment details¶
To begin, we can access each shipment plan in the parsed response like so:
# Using the `resp` object from our previous examples
for plan in resp.parsed.InboundShipmentPlans.member:
...
Each plan
contains metadata required for creating a new shipment. These include:
plan.ShipmentId
, the FBA shipment ID Amazon generates for the new shipment plan.plan.DestinationFulfillmentCenterId
, the short code for a Fulfillment Center planning to receive this shipment.plan.LabelPrepType
, the label preparation type for this shipment.
In addition to these data points, you should consider gathering the following data as arguments for the
create_inbound_shipment
request method:
shipment_name
(required), a human-readable name to help identify your shipment without relying on shipment IDs.shipment_status
, the initial status of the shipment. Defaults to “WORKING”, indicating the shipment will remain “open” so that items and quantities can still be changed before it is shipped.The following constants can be used for this argument:
InboundShipments.STATUS_WORKING
InboundShipments.STATUS_SHIPPED
InboundShipments.STATUS_CANCELLED
InboundShipments.STATUS_CANCELED
(alias forSTATUS_CANCELLED
)
case_required
, a boolean indicating that items in the shipment are either all case-packed (ifTrue
) or all loose items (ifFalse
). Defaults toFalse
.box_contents_source
, a string indicating a source of box content data for packages within the shipment, orNone
indicating no box contents source. Defaults toNone
.The following constants can be used for this argument:
InboundShipments.BOX_CONTENTS_FEED
, indicating contents will be provided in a Feed of type_POST_FBA_INBOUND_CARTON_CONTENTS_
.InboundShipments.BOX_CONTENTS_2D_BARCODE
, indicating contents will be provided using 2D barcodes present on the cartons of the shipment.
We will illustrate how to use these data points later in this doc.
Converting plan items to shipment items¶
While the request to create_inbound_shipment_plan
makes use of the
InboundShipmentPlanRequestItem
model to
transmit item data, this model is not sufficient for passing data to create_inbound_shipment
and
update_inbound_shipment
requests, as they require slightly different parameters. We will need to use the
InboundShipmentItem
model, instead.
We can pass data to this model in one of three ways:
Manually processing item data from the response:
for plan in resp.parsed.InboundShipmentPlans.member: shipment_items = [] for item in plan.Items.member: new_item = inbound_api.InboundShipmentItem( sku=item.SellerSKU, quantity=item.Quantity, ) shipment_items.append(new_item)
Using
InboundShipmentItem.from_plan_item
to construct an item automatically from each item in the response:for plan in resp.parsed.InboundShipmentPlans.member: shipment_items = [] for item in plan.Items.member: new_item = inbound_api.InboundShipmentItem.from_plan_item(item) shipment_items.append(new_item)
Using helper method
shipment_items_from_plan
to return a list of items from the entire plan automatically:for plan in resp.parsed.InboundShipmentPlans.member: shipment_items = inbound_api.shipment_items_from_plan(plan)
Note
Using InboundShipmentItem.from_plan_item
or shipment_items_from_plan
, each item will automatically
store the fnsku
of each planned item. This data is ignored in calls to create_inbound_shipment
and
update_inbound_shipment
, but can be useful for tracking items internally.
Using either of these methods, the list of shipment_items
can be used as the items
argument to either the
create_inbound_shipment
or update_inbound_shipment
request method.
Adding quantity_in_case
and release_date
values
Item data provided by a plan
is sufficient for most data required for items, but some data points must be
added manually:
Case-pack information, specifically the
quantity_in_case
argument, is not supplied by the response fromcreate_inbound_shipment_plan
, even if this information was provided in the request itself.Pre-order items must provide an additional
release_date
data point.
In the first two examples above, these data points can be added as arguments when constructing the new item:
# using InboundShipmentItem(...):
new_item = inbound_api.InboundShipmentItem(
sku=item.SellerSKU,
quantity=item.Quantity,
quantity_in_case=...,
release_date=...,
)
# using InboundShipmentItem.from_plan_item(...):
new_item = inbound_api.InboundShipmentItem.from_plan_item(
item,
quantity_in_case=...,
release_date=...,
)
# Confirm this data has been added:
print(new_item.quantity_in_case, new_item.release_date)
In either case, when working with multiple items per shipment plan, you will need to determine which SKU these data
refer to. You should be able to rely on item.SellerSKU
to identify those SKUs.
Adding extra data when processing items in bulk
When processing a planned shipment’s items in bulk, adding quantity_in_case
and/or release_date
values to
each item can be done using the overrides
argument to shipment_items_from_plan
.
overrides
expects a dictionary with SellerSKUs as its keys. The values of this dict can be either:
A dict containing keys
quantity_in_case
and/orrelease_date
(all other keys are ignored):overrides = { 'mySku1': { 'quantity_in_case': 12, 'release_date': datetime.datetime(2020-12-25), }, }
An instance of
ExtraItemData
:overrides = { 'mySku2': inbound_api.ExtraItemData( quantity_in_case=12, release_date=datetime.datetime(2020-12-25), ), }
You should construct this set of overrides for all SKUs sent in your original request to
create_inbound_shipment_plan
. You can then use the same set of overrides on any planned shipment resulting
from that request:
overrides = {...}
for plan in resp.parsed.InboundShipmentPlans.member:
shipment_items = inbound_api.shipment_items_from_plan(plan, overrides=overrides)
Creating shipments¶
Putting everything together up to this point, we can create a new FBA shipment using the
create_inbound_shipment
method:
# with optional overrides
overrides = {
'mySku1': inbound_api.ExtraItemData(...),
'mySku2': inbound_api.ExtraItemData(...),
}
for plan in resp.parsed.InboundShipmentPlans.member:
# Gather our items for the planned shipment
shipment_items = inbound_api.shipment_items_from_plan(plan, overrides=overrides)
# Send the request to create a new shipment
new_shipment_resp = inbound_api.create_inbound_shipment(
shipment_id=plan.ShipmentId,
shipment_name="My Shiny New FBA Shipment",
destination=plan.DestinationFulfillmentCenterId,
items=shipment_items,
label_preference=plan.LabelPrepType,
)
For help with additional arguments - such as shipment_status
, case_required
, box_contents_source
,
or from_address
- see Gathering shipment details.
Updating shipments¶
Creating a shipment is not the end of the story, of course. It is sometimes necessary to make changes to an
already-created shipment. For this, we use
update_inbound_shipment
.
update_inbound_shipment
’s arguments are identical to those of create_inbound_shipment
, with the exception that
all arguments besides shipment_id
are optional. Generally, supplying a value to one of those arguments will
overwrite that value of the given shipment, such as:
Setting
shipment_status=InboundShipments.STATUS_CANCELLED
to cancel a shipment;Changing the
from_address
;etc.
Changing item quantities¶
Item quantities on a shipment can be changed by providing a list of InboundShipmentItem
instances for the items
argument of update_inbound_shipment
. The details of the submitted items will overwrite details of those items in the
existing shipment based on matching SellerSKUs.
Amazon will expect the total quantity for an item: there is no mechanism for adding or subtracting a quantity from the existing total. For example, if a shipment contains 24 units of an item and you want to add 12 of that item, you will need to submit a total quantity of 36 in the update request:
resp = inbound_api.update_inbound_shipment(
shipment_id="FBAMYSHIPMENT",
items=[
inbound_api.InboundShipmentItem(
sku="MySku1",
quantity=36,
)
]
)
It is up to you how you keep track of these quantity changes in your process. One way might be to cache these details
in some local database. Another might be querying the current total quantity using a request to
list_inbound_shipment_items
, then
calculating the new total:
my_shipment = "FBAMYSHIPMENT"
# Set our change quantities as "deltas", with SKU as key and the change as value
quantity_deltas = {
'mySku1': 12, # add 12
'mySku2': -6, # remove 6
}
update_items = []
list_resp = inbound_api.list_inbound_shipment_items(shipment_id=my_shipment)
for item in list_resp.parsed.ItemData.member:
if item.SellerSKU in quantity_deltas:
new_quantity = item.QuantityShipped + quantity_deltas[item.SellerSKU]
# Negative quantities not permitted, so set 0 as a minimum using `max`:
new_quantity = max([new_quantity, 0])
# Add items to a list for updates:
update_items.append(
inbound_api.InboundShipmentItem(item.SellerSKU, new_quantity)
)
if update_items:
update_resp = inbound_api.update_inbound_shipment(
shipment_id=my_shipment,
items=update_items,
)
Adding items from a new shipment plan¶
Under certain conditions, items from a new shipment plan can be added to one of your existing shipments in WORKING status. In this way, you can keep a shipment “open” in your own facility, adding new items to the same shipment before “closing” it and sending it to Amazon’s fulfillment network.
Follow the same steps as Requesting a shipment plan, then inspect the contents of the planned shipments (see Processing shipment plans).
Generally, you may be able to add newly-planned items to an existing shipment if the following details match in the target “WORKING” shipment:
DestinationFulfillmentCenterId
LabelPrepType
Whether both shipments are designated for hazmat items.
Note
In the author’s experience, this detail may not be apparent through MWS ahead of time: you may simply need to attempt to add the item and handle whatever error occurs afterward.
Forgiveness instead of permission, as they say.
Whether the two shipments require case packs or not.
This list is not exhaustive, so use best judgment and follow Amazon’s guidance where necessary.
If you determine that a planned item can be added to one of your existing shipments, add that item to an
update_inbound_shipment
request for the given shipment ID.
As mentioned in Changing item quantities, remember to use the total quantity of an item being updated, not
the change in quantity, if the item is already present in the given shipment. If you are not tracking these quantities
in your own application, you may wish to send a request to
list_inbound_shipment_items
to
obtain the current quantity of a matching item before sending the update request.
Using Parsed XML Responses¶
New in version 1.0dev15: MWSResponse
and DotDict
added.
Warning
The following pertains to features added in v1.0dev15 related to MWS requests.
These features are disabled by default. To use these features, set flag _use_feature_mwsresponse
to True
on an API class instance before making any requests:
api_class = Orders(...)
api_class._use_feature_mwsresponse = True
If the flag is False
, all requests will return either DictWrapper
or DataWrapper
objects (deprecated);
and parsed XML contents will be returned as an instance of ObjectDict
(deprecated).
New features using MWSResponse
and DotDict
will become the default in v1.0.
For most MWS operations, the returned response is an XML documents encoded using ISO 8859-1. python-amazon-mws will wrap all responses
in an instance of MWSResponse
, which then parses these responses automatically
using the xmltodict
package. This parsed content is then available from the
MWSResponse.parsed
property.
Below, we’ll go into more detail on how to use MWSResponse.parsed
in your application to get the most from
these XML responses.
How XML responses are parsed in python-amazon-mws¶
XML responses from MWS typically look like the following example (adapted from an example in MWS documentation):
<?xml version="1.0"?>
<ListMatchingProductsResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<ListMatchingProductsResult>
<Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>059035342X</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-US">
<ns2:Binding>Paperback</ns2:Binding>
<ns2:Brand>Scholastic Press</ns2:Brand>
<ns2:Creator Role="Illustrator">GrandPré, Mary</ns2:Creator>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
</Product>
</Products>
</ListMatchingProductsResult>
<ResponseMetadata>
<RequestId>3b805a12-689a-4367-ba86-EXAMPLE91c0b</RequestId>
</ResponseMetadata>
</ListMatchingProductsResponse>
Parsing of this document goes through the following steps in python-amazon-mws:
All requests are sent through the
requests
package, and responses are returned as arequests.Response
instance.The
Response
object is then wrapped byMWSResponse
, and stored internally asMWSResponse.original
.If the response did not specify an encoding in its headers,
MWSResponse
will call onrequests.Response.apparent_encoding
explicitly to force character set detection. For most use cases, this will allow theMWSResponse.text
property to decode the response content properly.Note
if a different encoding is required, you can alter
MWSResponse.encoding
before accessingMWSResponse.text
, or work with the rawMWSResponse.content
.You can also initialize an API class instance with a
force_response_encoding='my-encoding'
argument. This will override the encoding used to decode all responses from that API’s requests. This is useful when you are confident that responses are being encoded differently, such as when responses are actually encoded in UTF-8 (despite Amazon’s documentation to the contrary).MWSResponse.parse_response()
is called, which:Produces a “clean” copy of the XML document to use for parsing (see XML “cleaning” before parsing). (The original response content is left unchanged: only a copy is used for parsing.)
Runs
MWSResponse.text
through the utilitymws.utils.xml.mws_xml_to_dict
. This usesxmltodict.parse()
to convert the XML to a standard Python dictionary, which is returned and stored asMWSResponse._dict
.Wraps the parsed Python dict in a
DotDict
, which can be accessed fromMWSResponse.parsed
.If the response contains a
<ResponseMetadata>
tag, this method also builds aDotDict
instance of this key only, storing it asMWSResponse.metadata
. Typically this tag only contains the<RequestId>
element, so the propertyMWSResponse.request_id
can also be used to access this value.
Once parsing is complete, the MWSResponse
instance is returned. From this
instance, we can access the DotDict
that is returned from its
.parsed
property to comb through the returned data.
For more details on how to make the best use of this parsed data, please see DotDict.
Result keys and metadata¶
Most MWS requests returning XML documents take the following overall shape:
<?xml version="1.0"?>
<OperationResponse>
<OperationResult>
...
</OperationResult>
<ResponseMetadata>
<RequestId>...</RequestId>
</ResponseMetadata>
</OperationResponse>
The parsed document initially returns a dict
with just two keys. For the above example, that would look like so:
{
'OperationResult': ...,
'ResponseMetadata': ...,
}
Note
Operation
in all above examples would be replaced by the name of the MWS operation that was called.
For the ListInboundShipments
operation, for example, the document’s root will be
ListInboundShipmentsResponse
, and the result key will be ListInboundShipmentsResult
.
Both the ...Result
key and ResponseMetadata
are accessible from
MWSResponse
through separate properties:
The
...Result
key is used as the root forMWSResponse.parsed
, so accessing.parsed
should only return parsed content found inside the<...Result>
tag.ResponseMetadata
is accessible fromMWSResponse.metadata
. You can access theRequestId
stored there either asMWSResponse.metadata.RequestId
or through the shortcut property,MWSResponse.request_id
.
Tip
Amazon recommends
logging RequestId
as well as the request timestamp (found in
MWSResponse.timestamp
) to aid in troubleshooting when contacting
their support channels.
XML “cleaning” before parsing¶
MWS XML responses may be returned with a variety of data that does not fit well into Python data structures During parsing of these responses, python-amazon-mws either removes or finesses some of this data into a “cleaner” format.
Consider the example response from earlier:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <?xml version="1.0"?>
<ListMatchingProductsResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<ListMatchingProductsResult>
<Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>059035342X</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-US">
<ns2:Binding>Paperback</ns2:Binding>
<ns2:Brand>Scholastic Press</ns2:Brand>
<ns2:Creator Role="Illustrator">GrandPré, Mary</ns2:Creator>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
</Product>
</Products>
</ListMatchingProductsResult>
<ResponseMetadata>
<RequestId>3b805a12-689a-4367-ba86-EXAMPLE91c0b</RequestId>
</ResponseMetadata>
</ListMatchingProductsResponse>
|
This document will be “cleaned” as follows:
The document’s root tag - in this case
<ListMatchingProductsResponse>
- will be ignored. The parsed Python dict will take the shape of:{ 'ListMatchingProductsResult': ..., 'ResponseMetadata': ... }
Namespaces are removed. For instance, the
<Products>
tag (line 4) will have both namespaces stripped, leaving only the bare tag name.Prefixes - such as
ns2:
orxml:
, seen on lines 13 through 17 - are removed from tag names and attributes. The tag<ns2:ItemAttributes xml:lang="en-US">
on line 13 will be stripped down to just<ItemAttributes lang="en-US">
prior to being parsed.
Feeds¶
According to Amazon’s documentation:
The Amazon MWS Feeds API section of the Amazon Marketplace Web Service (Amazon MWS) API lets you upload inventory and order data to Amazon. You can also use the Amazon MWS Feeds API section to get information about the processing of feeds.
More details on how to utilize the Feeds API per MWS requirements can be
found at the above link. Below we’ll provide details on how to use this API
with Feeds
.
Uploading metadata for VAT invoices¶
Metadata for VAT invoices is processed as a FeedOptions
parameter to the SubmitFeed
operation, as described in
Amazon’s documentation, Invoice Uploader Developer Guide (PDF)
This parameter is not described in the standard MWS developer documentation, unfortunately, which can lead to some
confusion.
When submitting a feed, you can either build the metadata string yourself following the above guidelines,
or provide a dict to the feed_options
arg for Feeds.submit_feed
:
from mws import Feeds, Marketplaces
feeds_api = Feeds(MY_ACCESS_KEY, MY_SECRET_KEY, MY_ACCOUNT_ID)
feed_opts = {'orderid': '407-XXXXXX-6760332', 'invoicenumber': 51}
response = feeds_api.submit_feed(
feed=my_invoice_file.encode(),
feed_type='_UPLOAD_VAT_INVOICE_',
feed_options=feed_opts,
marketplace_ids=Marketplaces.UK.marketplace_id,
)
The above will automatically convert feed_opts
into the formatted string
'metadata:orderid=407-XXXXXX-6760332;metadata:invoicenumber=51'
when the request is sent.
You can also send this same string as feed_options
, if you wish to perform your own formatting:
response = feeds_api.submit_feed(
feed=my_invoice_file.encode(),
feed_type='_UPLOAD_VAT_INVOICE_',
feed_options='metadata:orderid=407-XXXXXX-6760332;metadata:invoicenumber=51',
marketplace_ids=Marketplaces.UK.marketplace_id,
)
Note
The format for the FeedOptions string is described in Amazon’s documentation here (PDF). You are welcome to format your own FeedOptions string, if you find that the python-amazon-mws implementation is not suitable for your specific needs.
You can find our implementation for this formatting within the source for Feeds
.
Feeds API reference¶
-
class
mws.
Feeds
(access_key, secret_key, account_id, region='US', uri='', version='', auth_token='', proxy=None, user_agent_str='', headers=None, force_response_encoding=None)[source]¶ Amazon MWS Feeds API.
Docs: https://docs.developer.amazonservices.com/en_US/feeds/Feeds_Overview.html
-
submit_feed
(feed, feed_type, feed_options=None, marketplace_ids=None, amazon_order_id=None, document_type=None, content_type='text/xml', purge=False)[source]¶ The SubmitFeed operation. Uploads a feed for processing by Amazon MWS.
Requires
feed
, a file in XML or flat-file format encoded to bytes; andfeed_type
, a string detailing a FeedType enumeration.All other parameters may change depending on the
feed_type
you select. See Amazon docs for details.feed_options
is used forfeed_type
“_UPLOAD_VAT_INVOICE_”, to provide FeedOption metadata. See Invoice Uploader Developer Guide (PDF), for details. Can accept a dict of simple key-value pairs, which will be converted to the proper string format automatically.marketplace_ids
accepts a list of one or more marketplace IDs where you want the feed to be applied. Can also accept a single marketplace ID as a string.amazon_order_id
anddocument_type
are used forfeed_type
“_POST_EASYSHIP_DOCUMENTS_”, used for Amazon Easy Ship orders (available only in India marketplace). Provide an Amazon Order ID as a string and the type of PDF document (“ShippingLabel”, “Invoice”, or “Warranty”; or None to get all).content_type
sets the “Content-Type” request header, indicating the type of file being sent. Defaults to"text/xml"
.purge
enables Amazon’s “purge and replace” functionality. Set toTrue
to purge and replace existing data, otherwise useFalse
(the default). Only applies to product-related flat file feed types. Use only in exceptional cases. Usage is throttled to allow only one purge and replace within a 24-hour period.
-
get_feed_submission_list
(feed_ids=None, max_count=None, feed_types=None, processing_statuses=None, from_date=None, to_date=None, next_token=None)[source]¶ Returns a list of all feed submissions submitted between from_date and to_date. If these params are omitted, defaults to the previous 90 days.
Pass next_token to call “GetFeedSubmissionListByNextToken” instead.
Docs: https://docs.developer.amazonservices.com/en_US/feeds/Feeds_GetFeedSubmissionList.html
-
get_feed_submission_list_by_next_token
(token)[source]¶ Alias for get_feed_submission_list(next_token=token).
Docs: https://docs.developer.amazonservices.com/en_US/feeds/Feeds_GetFeedSubmissionListByNextToken.html
-
get_feed_submission_count
(feed_types=None, processing_statuses=None, from_date=None, to_date=None)[source]¶ Returns a count of the feeds submitted between from_date and to_date. If these params are omitted, defaults to the previous 90 days.
Docs: https://docs.developer.amazonservices.com/en_US/feeds/Feeds_GetFeedSubmissionCount.html
-
cancel_feed_submissions
(feed_ids=None, feed_types=None, from_date=None, to_date=None)[source]¶ Cancels one or more feed submissions and returns a count of the feed submissions that were canceled.
Docs: https://docs.developer.amazonservices.com/en_US/feeds/Feeds_CancelFeedSubmissions.html
-
get_feed_submission_result
(feed_id)[source]¶ Returns the feed processing report and the Content-MD5 header.
Docs: https://docs.developer.amazonservices.com/en_US/feeds/Feeds_GetFeedSubmissionResult.html
-
class
FeedProcessingStatus
(value)¶ Enumerates all the feed processing status values that are available through the Feeds API section.
-
class
FeedType
(value)¶ Enumerates all the feed types that are available through the Feeds API section.
MWS Docs: FeedType enumeration
Please refer to MWS documentation for details on each FeedType, including usage, template files, and additional information links.
-
InboundShipments¶
According to Amazon’s documentation:
With the Fulfillment Inbound Shipment API section of Amazon Marketplace Web Service (Amazon MWS), you can create and update inbound shipments of inventory in Amazon’s fulfillment network. You can also request lists of inbound shipments or inbound shipment items based on criteria that you specify. After your inventory has been received in the fulfillment network, Amazon can fulfill your orders regardless of whether you are selling on Amazon’s retail web site or through other retail channels.
InboundShipments API reference¶
-
class
mws.
InboundShipments
(*args, **kwargs)[source]¶ Amazon MWS FulfillmentInboundShipment API
MWS docs: FulfillmentInboundShipment Overview
-
set_ship_from_address
(address)[source]¶ DEPRECATED, remove later. Now an alias to assigning
from_address
property directly.- Parameters
address (Union[mws.models.inbound_shipments.Address, dict]) –
-
from_address_params
(from_address=None, prefix='')[source]¶ Converts a from address, either stored or passed as an argument, to params.
If provided as an argument, checks first that the arg is the correct type, raising MWSError if it’s not an instance of the Address model.
Providing a from_address as an argument will override any address stored on this API instance.
- Parameters
from_address (Optional[mws.models.inbound_shipments.Address]) –
prefix (str) –
- Return type
dict
-
get_inbound_guidance_for_sku
(skus, marketplace_id)[source]¶ Returns inbound guidance for a list of items by Seller SKU.
skus
expects some iterable of strings. If it is any other type of object, it will be treated as a single instance and wrapped in a list first, similar to passing[skus]
.MWS docs: GetInboundGuidanceForSKU
- Parameters
skus (Union[List[str], str]) –
marketplace_id (str) –
-
get_inbound_guidance_for_asin
(asins, marketplace_id)[source]¶ Returns inbound guidance for a list of items by ASIN.
asins
expects some iterable of strings. If it is any other type of object, it will be treated as a single instance and wrapped in a list first, similar to passing[asins]
.MWS docs: GetInboundGuidanceForASIN
- Parameters
asins (Union[List[str], str]) –
marketplace_id (str) –
-
create_inbound_shipment_plan
(items, country_code='US', subdivision_code=None, label_preference=None, from_address=None)[source]¶ Returns one or more inbound shipment plans, which provide the information you need to create inbound shipments.
items
expects a list ofInboundShipmentPlanRequestItem
model instances. Also supports a list of “legacy” dictionaries, in which the keys ‘sku’ and ‘quantity’ are required; and keys ‘asin’, ‘condition’, and ‘quantity_in_case’ are optional.Note that the dictionary format does not support adding
PrepDetails
, as theInboundShipmentPlanRequestItem
model does.
If
from_address
is not provided (with an instance of theAddress
model), then the.from_address
attribute of this class instance must be set before using this operation.MWS docs: CreateInboundShipmentPlan
- Parameters
items (List[Union[mws.models.inbound_shipments.InboundShipmentPlanRequestItem, dict]]) –
country_code (str) –
subdivision_code (Optional[str]) –
label_preference (Optional[str]) –
from_address (Optional[mws.models.inbound_shipments.Address]) –
-
create_inbound_shipment
(shipment_id, shipment_name, destination, items, shipment_status='WORKING', label_preference=None, case_required=False, box_contents_source=None, from_address=None)[source]¶ Creates an inbound shipment to Amazon’s fulfillment network.
items
expects a list ofInboundShipmentItem
model instances. Also supports a list of “legacy” dictionaries, in which the keys ‘sku’ and ‘quantity’ are required; and key ‘quantity_in_case’ is optional.Note that the dictionary format does not support adding
PrepDetails
, as theInboundShipmentItem
model does.The model also supports adding
release_date
, which the dictionary does not.
If
from_address
is not provided (with an instance of theAddress
model), then the.from_address
attribute of this class instance must be set before using this operation.MWS docs: CreateInboundShipment
- Parameters
shipment_id (str) –
shipment_name (str) –
destination (str) –
items (List[Union[mws.models.inbound_shipments.InboundShipmentItem, dict]]) –
shipment_status (str) –
label_preference (Optional[str]) –
case_required (bool) –
box_contents_source (Optional[str]) –
from_address (Optional[mws.models.inbound_shipments.Address]) –
-
update_inbound_shipment
(shipment_id, shipment_name=None, destination=None, items=None, shipment_status=None, label_preference=None, case_required=None, box_contents_source=None, from_address=None)[source]¶ Updates an existing inbound shipment in Amazon FBA.
items
expects a list ofInboundShipmentItem
model instances. Also supports a list of “legacy” dictionaries, in which the keys ‘sku’ and ‘quantity’ are required; and key ‘quantity_in_case’ is optional.Note that the dictionary format does not support adding
PrepDetails
, as theInboundShipmentItem
model does.The model also supports adding
release_date
, which the dictionary does not.
If
from_address
is not provided (with an instance of theAddress
model), then the.from_address
attribute of this class instance must be set before using this operation.MWS docs: UpdateInboundShipment
- Parameters
shipment_id (str) –
shipment_name (Optional[str]) –
destination (Optional[str]) –
items (Optional[List[Union[mws.models.inbound_shipments.InboundShipmentItem, dict]]]) –
shipment_status (Optional[str]) –
label_preference (Optional[str]) –
case_required (Optional[bool]) –
box_contents_source (Optional[str]) –
from_address (Optional[mws.models.inbound_shipments.Address]) –
-
get_preorder_info
(shipment_id)[source]¶ Returns pre-order information, including dates, that a seller needs before confirming a shipment for pre-order. Also indicates if a shipment has already been confirmed for pre-order.
- Parameters
shipment_id (str) –
-
confirm_preorder
(shipment_id, need_by_date)[source]¶ Confirms a shipment for pre-order.
- Parameters
shipment_id (str) –
need_by_date (datetime.datetime) –
-
get_prep_instructions_for_sku
(skus, country_code='US')[source]¶ Returns labeling requirements and item preparation instructions to help you prepare items for an inbound shipment.
MWS docs: GetPrepInstructionsForSKU
- Parameters
skus (Union[List[str], str]) –
country_code (str) –
-
get_prep_instructions_for_asin
(asins, country_code='US')[source]¶ Returns item preparation instructions to help with item sourcing decisions.
MWS docs: GetPrepInstructionsForASIN
- Parameters
asins (Union[List[str], str]) –
country_code (str) –
-
estimate_transport_request
(shipment_id)[source]¶ Requests an estimate of the shipping cost for an inbound shipment.
MWS docs: EstimateTransportRequest
- Parameters
shipment_id (str) –
-
get_transport_content
(shipment_id)[source]¶ Returns current transportation information about an inbound shipment.
- Parameters
shipment_id (str) –
-
confirm_transport_request
(shipment_id)[source]¶ Confirms that you accept the Amazon-partnered shipping estimate and you request that the Amazon-partnered carrier ship your inbound shipment.
MWS docs: ConfirmTransportRequest
- Parameters
shipment_id (str) –
-
void_transport_request
(shipment_id)[source]¶ Voids a previously-confirmed request to ship your inbound shipment using an Amazon-partnered carrier.
MWS docs: VoidTransportRequest
- Parameters
shipment_id (str) –
-
get_package_labels
(shipment_id, num_labels, page_type=None)[source]¶ Returns PDF document data for printing package labels for an inbound shipment.
- Parameters
shipment_id (str) –
num_labels (int) –
page_type (str) –
-
get_unique_package_labels
(shipment_id, page_type, package_ids)[source]¶ Returns unique package labels for faster and more accurate shipment processing at the Amazon fulfillment center.
shipment_id
must match a valid, current shipment.page_type
expected to be string matching one of following (not checked, in case Amazon requirements change):“PackageLabel_Letter_2”
“PackageLabel_Letter_6”
“PackageLabel_A4_2”
“PackageLabel_A4_4”
“PackageLabel_Plain_Paper”
package_ids
expects some iterable of strings or integers. If it is any other type of object, it will be treated as a single instance and wrapped in a list first, similar to passing[package_ids]
.MWS docs: GetUniquePackageLabels
- Parameters
shipment_id (str) –
page_type (str) –
package_ids (Union[Iterable[Union[str, int]], str, int]) –
-
get_pallet_labels
(shipment_id, page_type, num_labels)[source]¶ Returns
num_labels
number of pallet labels for shipmentshipment_id
of the givenpage_type
.Amazon expects
page_type
as a string matching one of following:“PackageLabel_Letter_2”
“PackageLabel_Letter_6”
“PackageLabel_A4_2”
“PackageLabel_A4_4”
“PackageLabel_Plain_Paper”
num_labels
is integer, number of labels to create.- Parameters
shipment_id (str) –
page_type (str) –
num_labels (int) –
-
get_bill_of_lading
(shipment_id)[source]¶ Returns PDF document data for printing a bill of lading for an inbound shipment.
- Parameters
shipment_id (str) –
-
list_inbound_shipments
(shipment_ids=None, shipment_statuses=None, last_updated_after=None, last_updated_before=None, next_token=None)[source]¶ Returns list of shipments based on statuses, IDs, and/or before/after datetimes.
Pass
next_token
to call “ListInboundShipmentsByNextToken” instead.MWS docs: ListInboundShipments
- Parameters
shipment_ids (Iterable[str]) –
shipment_statuses (Iterable[str]) –
last_updated_after (datetime.datetime) –
last_updated_before (datetime.datetime) –
next_token (str) –
-
list_inbound_shipments_by_next_token
(token)[source]¶ Alias for
list_inbound_shipments(next_token=token)
MWS docs: ListInboundShipmentsByNextToken
- Parameters
token (str) –
-
list_inbound_shipment_items
(shipment_id=None, last_updated_after=None, last_updated_before=None, next_token=None)[source]¶ Returns list of items within inbound shipments and/or before/after datetimes.
Pass
next_token
to call “ListInboundShipmentItemsByNextToken” instead.MWS docs: ListInboundShipmentItems
- Parameters
shipment_id (str) –
last_updated_after (datetime.datetime) –
last_updated_before (datetime.datetime) –
next_token (str) –
-
list_inbound_shipment_items_by_next_token
(token)[source]¶ Alias for
list_inbound_shipment_items(next_token=token)
MWS docs: ListInboundShipmentItemsByNextToken
- Parameters
token (str) –
-
Other tools¶
Note
The following classes and utility functions are attached to the
InboundShipments
class for convenient access. For example,
the Address
model can be accessed like so:
from mws import InboundShipments
my_address = InboundShipments.Address(...)
# or from an instance of InboundShipments:
inbound_api = InboundShipments(...)
my_address = inbound_api.Address(...)
Data models¶
-
class
mws.models.inbound_shipments.
Address
(name=None, address_line_1=None, address_line_2=None, city=None, district_or_county=None, state_or_province_code=None, country_code='US', postal_code=None)[source]¶ Postal address information.
-
classmethod
from_legacy_dict
(value)[source]¶ Create an Address from a legacy structured dict.
- Parameters
value (dict) –
- Return type
-
to_params
(prefix='')¶ Flattens all parameters and values of this model into a single key-value dictionary, suitable for use in a request to MWS.
- Parameters
prefix (str) –
- Return type
dict
-
classmethod
-
class
mws.models.inbound_shipments.
PrepDetails
(prep_instruction, prep_owner='SELLER')[source]¶ A preparation instruction, and who is responsible for that preparation.
MWS docs: PrepDetails Datatype
prep_instruction
accepts either a string or an instance of thePrepInstruction
enum, detailing the type of prep to perform.prep_owner
(optional) accepts a string, typically “AMAZON” or “SELLER”, to indicate who is responsible for the prep. You can usePrepDetails.AMAZON
orPrepDetails.SELLER
to fill in these values. Defaults to “SELLER”.-
to_params
(prefix='')¶ Flattens all parameters and values of this model into a single key-value dictionary, suitable for use in a request to MWS.
- Parameters
prefix (str) –
- Return type
dict
-
-
class
mws.models.inbound_shipments.
InboundShipmentPlanRequestItem
(*args, asin=None, condition=None, **kwargs)[source]¶ Item information for creating an inbound shipment plan. Submitted with a call to the CreateInboundShipmentPlan operation.
MWS docs: InboundShipmentPlanRequestItem Datatype
Adds the optional arguments
asin
(to include ASIN as needed) andcondition
(to add item condition information).condition
may be a string or an instance ofItemCondition
.-
to_params
(prefix='')¶ Flattens all parameters and values of this model into a single key-value dictionary, suitable for use in a request to MWS.
- Parameters
prefix (str) –
- Return type
dict
-
-
class
mws.models.inbound_shipments.
InboundShipmentItem
(*args, release_date=None, **kwargs)[source]¶ Item information for an inbound shipment. Submitted with a call to the CreateInboundShipment or UpdateInboundShipment operation.
MWS docs: InboundShipmentItem Datatype
-
classmethod
from_plan_item
(item, quantity_in_case=None, release_date=None)[source]¶ Construct this model from a shipment plan returned from a CreateInboundShipmentPlan request.
Expects a
DotDict
instance that can typically be found in the parsed response object by:Iterating
for plan in resp.parsed.InboundShipmentPlans.member:
; andIterating
for item in plan.Items.member:
.
Each
item
instance in the above example should work here [YMMV].quantity_in_case
must be passed manually for case-packed shipments, even when constructing from a shipment plan response, as this data is not typically returned in the plan details.release_date
is also not part of a shipment plan response, so this must be passed manually in order to add it to the item.- Parameters
item (mws.utils.collections.DotDict) –
quantity_in_case (Optional[int]) –
release_date (Optional[datetime.datetime]) –
- Return type
-
to_params
(prefix='')¶ Flattens all parameters and values of this model into a single key-value dictionary, suitable for use in a request to MWS.
- Parameters
prefix (str) –
- Return type
dict
-
classmethod
Enums¶
-
class
mws.models.inbound_shipments.
PrepInstruction
(value)[source]¶ Bases:
enum.Enum
Enumeration of preparation instruction types.
MWS docs: PrepInstruction Datatype
-
POLYBAGGING
= 'Polybagging'¶
-
BUBBLEWRAPPING
= 'BubbleWrapping'¶
-
TAPING
= 'Taping'¶
-
BLACKSHRINKWRAPPING
= 'BlackShrinkWrapping'¶
-
LABELING
= 'Labeling'¶
-
HANGGARMENT
= 'HangGarment'¶
-
-
class
mws.models.inbound_shipments.
ItemCondition
(value)[source]¶ Bases:
str
,enum.Enum
Condition value for an item included with a CreateInboundShipmentPlan request. Values are defined within the InboundShipmentPlanRequestItem Datatype documentation.
-
NEW_ITEM
= 'NewItem'¶
-
NEW_WITH_WARRANTY
= 'NewWithWarranty'¶
-
NEW_OEM
= 'NewOEM'¶
-
NEW_OPEN_BOX
= 'NewOpenBox'¶
-
USED_LIKE_NEW
= 'UsedLikeNew'¶
-
USED_VERY_GOOD
= 'UsedVeryGood'¶
-
USED_GOOD
= 'UsedGood'¶
-
USED_ACCEPTABLE
= 'UsedAcceptable'¶
-
USED_POOR
= 'UsedPoor'¶
-
USED_REFURBISHED
= 'UsedRefurbished'¶
-
COLLECTIBLE_LIKE_NEW
= 'CollectibleLikeNew'¶
-
COLLECTIBLE_VERY_GOOD
= 'CollectibleVeryGood'¶
-
COLLECTIBLE_GOOD
= 'CollectibleGood'¶
-
COLLECTIBLE_ACCEPTABLE
= 'CollectibleAcceptable'¶
-
COLLECTIBLE_POOR
= 'CollectiblePoor'¶
-
REFURBISHED_WITH_WARRANTY
= 'RefurbishedWithWarranty'¶
-
REFURBISHED
= 'Refurbished'¶
-
CLUB
= 'Club'¶
-
Utilities¶
-
mws.models.inbound_shipments.
shipment_items_from_plan
(plan, overrides=None)[source]¶ Given a shipment plan response, returns a list of
InboundShipmentItem
models constructed from the contents of that plan’sItems
set.Expects
plan
to be a node from a parsed MWS response from thecreate_inbound_shipment_plan
request, typically theresp.parsed.InboundShipmentPlans.member
node (which may be aDotDict
for a single plan or a list ofDotDict
instances for multiple; though both options should be natively iterable with the same interface).Providing
overrides
allows the addition of details that are not returned bycreate_inbound_shipment_plan
, such asquantity_in_case
andrelease_date
. Expects a dict where SellerSKUs are keys and the values are either instances ofExtraItemData
or dictionaries with the keysquantity_in_case
and/orrelease_date
. Only items matching a SellerSKU key inoverrides
will have data overridden this way.For example usage, see: Converting plan items to shipment items
- Parameters
plan (Union[mws.utils.collections.DotDict, List[mws.utils.collections.DotDict]]) –
overrides (Optional[Dict[str, mws.models.inbound_shipments.ExtraItemData]]) –
- Return type
-
class
mws.models.inbound_shipments.
ExtraItemData
(quantity_in_case=None, release_date=None)[source]¶ Dataclass used for providing overrides to individual SKUs when processing items from a planned shipment in bulk using
shipment_items_from_plan()
.To utilize this data, construct a dictionary that maps SellerSKUs to instances of this class, then pass that dictionary to the
overrides
argument forshipment_items_from_plan
.Example:
override_data = { # with a case quantity "MySku1": ExtraItemData(quantity_in_case=12), # a release date "MySku2": ExtraItemData(release_date=datetime.datetime(2021, 1, 28)), # or both (short version) "MySku3": ExtraItemData(24, datetime.datetime(2021, 1, 28)), } data = shipment_items_from_plan(plan, override_data)
Products¶
According to Amazon’s documentation:
The Products API section of Amazon Marketplace Web Service (Amazon MWS) helps you get information to match your products to existing product listings on Amazon Marketplace websites and to make sourcing and pricing decisions for listing those products on Amazon Marketplace websites. The Amazon MWS Products API returns product attributes, current Marketplace pricing information, and a variety of other product and listing information.
Using examples on this page¶
All examples below assume you have setup your Products API instance appropriately. Refer to Getting started for details:
from mws import Products
products_api = Products(
access_key="...",
secret_key="...",
account_id="...",
auth_token="...",
)
All request methods in the Products API also require a MarketplaceId to specify which marketplace the products are sold in. MarketplaceId values should match one of the values specified in Amazon documentation: Amazon MWS endpoints and MarkeplaceId values
python-amazon-mws makes these values available through the Marketplaces
Enum, which
contains both the endpoint
and marketplace_id
for each Amazon region via that region’s country code.
For convenience, a Marketplaces
instance will return its MarketplaceId through the .value
attribute, as well.
Further, all request methods in python-amazon-mws will automatically “clean” Enum instances by returning their .value
attributes.
The following are all valid methods for obtaining, for example, the MarketplaceId for the US region and passing it
to a request method in the Products
API:
from mws import Marketplaces
my_market = Marketplaces.US
# Returns the Enum instance for the US region.
# When used in a request method, the `marketplace_id` value will be used automatically.
print(my_market.marketplace_id)
# 'ATVPDKIKX0DER'
print(my_market.value)
# 'ATVPDKIKX0DER'
# (alias for `.marketplace_id`)
# You can also return the endpoint for that region, if needed:
print(my_market.endpoint)
# 'https://mws.amazonservices.com'
In all examples below, replace my_market
with the Marketplaces
Enum instance or MarketplaceId string value
relevant to your region.
Products API reference¶
-
class
mws.
Products
(access_key, secret_key, account_id, region='US', uri='', version='', auth_token='', proxy=None, user_agent_str='', headers=None, force_response_encoding=None)[source]¶ Amazon MWS Products API
MWS Docs: Products API Overview
-
list_matching_products
(marketplace_id, query, context_id=None)[source]¶ Returns a list of products and their attributes, based on a search query.
MWS Docs: ListMatchingProducts
Examples:
Obtaining ASINs for products returned by the query
"Python"
:resp = products_api.list_matching_products( marketplace_id=my_market, query="Python", ) for product in resp.parsed.Products.Product: asin = product.Identifiers.MarketplaceASIN.ASIN print(f"ASIN: {asin}")
Note
As a shorthand, you may access the first product from the response using a list index:
resp.parsed.Products.Product[0].Identifiers.MarketplaceASIN.ASIN
Beware: if only one product is returned, this may result in an error, as the
Product
node will not be a list. Iterating nodes is generally safer to avoid this issue (see: DotDict Native Iteration).Returning sales rank categories and rank numbers:
for product in resp.parsed.Products.Product: for rank in product.SalesRankings.SalesRank: category_id = rank.ProductCategoryId sales_rank = rank.Rank print(f"Category: {category_id}, Rank: {sales_rank}")
Returning product titles:
for product in resp.parsed.Products.Product: product_title = product.AttributeSets.ItemAttributes.Title print(f"Title: {product_title}")
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
query (str) –
context_id (Optional[str]) –
-
get_matching_product
(marketplace_id, asins)[source]¶ Returns a list of products and their attributes, based on a list of ASIN values.
Example
resp = products_api.get_matching_product( marketplace_id=my_market, asins=["B085G58KWT", "B07ZZW7QCM"], ) # Iterate over products returned by the request for product in resp.parsed.Product: # Access identifiers print(product.Identifiers.MarketplaceASIN.ASIN) print(product.Identifiers.MarketplaceASIN.MarketplaceId) # Attributes of the product, for instance a ListPrice (by amount and currency code): print(product.AttributeSets.ItemAttributes.ListPrice.Amount) print(product.AttributeSets.ItemAttributes.ListPrice.CurrencyCode)
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
asins (Union[List[str], str]) –
-
get_matching_product_for_id
(marketplace_id: str, type_: str, ids: Union[List[str], str])[source]¶ Returns a list of products and their attributes, based on a list of ASIN, GCID, SellerSKU, UPC, EAN, ISBN, and JAN values.
MWS Docs: GetMatchingProductForId
Example
resp = products_api.get_matching_product_for_id( marketplace_id=my_market, type_="ASIN", ids=["B085G58KWT", "B07ZZW7QCM"], )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
type_ (str) –
ids (Union[List[str], str]) –
-
get_competitive_pricing_for_sku
(marketplace_id, skus)[source]¶ Returns the current competitive price of a product, based on SellerSKU.
MWS Docs: GetCompetitivePricingForSKU
Example
resp = products_api.get_competitive_pricing_for_sku( marketplace_id=my_market, skus=["OO-NL0F-795Z"], ) for product in resp.parsed.Product: product.CompetitivePricing.NumberOfOfferListings product.CompetitivePricing.CompetitivePrices.CompetitivePrice.Price.LandedPrice.Amount
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
skus (Union[List[str], str]) –
-
get_competitive_pricing_for_asin
(marketplace_id, asins)[source]¶ Returns the current competitive price of a product, based on ASIN.
MWS Docs: GetCompetitivePricingForASIN
Example
resp = products_api.get_competitive_pricing_for_asin( marketplace_id=my_market, asins=["B085G58KWT"], )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
asins (Union[List[str], str]) –
-
get_lowest_offer_listings_for_sku
(marketplace_id, skus, condition='Any', exclude_me=False)[source]¶ Returns pricing information for the lowest-price active offer listings for up to 20 products, based on SellerSKU.
MWS Docs: GetLowestOfferListingsForSKU
Example
resp = products_api.get_lowest_offer_listings_for_sku( marketplace_id=my_market, skus=["OO-NL0F-795Z"], condition="New" # Any, New, Used, Collectible, Refurbished, Club. Default = Any )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
skus (Union[List[str], str]) –
condition (str) –
exclude_me (bool) –
-
get_lowest_offer_listings_for_asin
(marketplace_id, asins, condition='Any', exclude_me=False)[source]¶ Returns pricing information for the lowest-price active offer listings for up to 20 products, based on ASIN.
MWS Docs: GetLowestOfferListingsForASIN
Example
resp = products_api.get_lowest_offer_listings_for_asin( marketplace_id=my_market, asins=["B085G58KWT"], condition="New" # Any, New, Used, Collectible, Refurbished, Club. Default = Any )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
asins (Union[List[str], str]) –
condition (str) –
exclude_me (bool) –
-
get_lowest_priced_offers_for_sku
(marketplace_id, sku, condition='New', exclude_me=False)[source]¶ Returns lowest priced offers for a single product, based on SellerSKU.
MWS Docs: GetLowestPricedOffersForSKU
Example
resp = products_api.get_lowest_priced_offers_for_sku( marketplace_id=my_market, skus=["OO-NL0F-795Z"], condition="New" # Any, New, Used, Collectible, Refurbished, Club. Default = Any )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
sku (str) –
condition (str) –
exclude_me (bool) –
-
get_lowest_priced_offers_for_asin
(marketplace_id, asin, condition='New', exclude_me=False)[source]¶ Returns lowest priced offers for a single product, based on ASIN.
MWS Docs: GetLowestPricedOffersForASIN
Example
resp = products_api.get_lowest_priced_offers_for_asin( marketplace_id=my_market, asins=["B085G58KWT"], condition="New" # Any, New, Used, Collectible, Refurbished, Club. Default = Any )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
asin (str) –
condition (str) –
exclude_me (bool) –
-
get_my_fees_estimate
(fees_estimate, *fees_estimates)[source]¶ Returns the estimated fees for a list of products.
Accepts one or more
FeesEstimateRequest
instances as arguments:Example
estimate_request = FeesEstimateRequest(...) resp = products_api.get_my_fees_estimate(estimate_request)
Multiple estimates can be requested at the same time, as well:
estimate_request1 = FeesEstimateRequest(...) estimate_request2 = FeesEstimateRequest(...) resp = products_api.get_my_fees_estimate(estimate_request1, estimate_request2, ...)
- Parameters
fees_estimate (mws.models.products.FeesEstimateRequest) –
fees_estimates (mws.models.products.FeesEstimateRequest) –
-
get_my_price_for_sku
(marketplace_id, skus, condition=None)[source]¶ Returns pricing information for your own offer listings, based on SellerSKU.
Example
resp = products_api.get_my_price_for_sku( marketplace_id = my_market, skus="OO-NL0F-795Z", condition="New" # Any, New, Used, Collectible, Refurbished, Club. Default = All )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
skus (Union[List[str], str]) –
condition (Optional[str]) –
-
get_my_price_for_asin
(marketplace_id, asins, condition=None)[source]¶ Returns pricing information for your own offer listings, based on ASIN.
Example
resp = products_api.get_my_price_for_asin( marketplace_id=my_market, asins="B07QR73T66", condition="New" # Any, New, Used, Collectible, Refurbished, Club. Default = All )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
asins (Union[List[str], str]) –
condition (Optional[str]) –
-
get_product_categories_for_sku
(marketplace_id, sku)[source]¶ Returns the parent product categories that a product belongs to, based on SellerSKU.
MWS Docs: GetProductCategoriesForSKU
Example
resp = products_api.get_product_categories_for_sku( marketplace_id=my_market, sku="OO-NL0F-795Z" )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
sku (str) –
-
get_product_categories_for_asin
(marketplace_id, asin)[source]¶ Returns the parent product categories that a product belongs to, based on ASIN.
MWS Docs: GetProductCategoriesForASIN
Example
resp = products_api.get_product_categories_for_asin( marketplace_id=my_market, asin="B07QR73T66" )
- Parameters
marketplace_id (Union[mws.mws.Marketplaces, str]) –
asin (str) –
-
Data models¶
Several data models are attached to the Products
API class, either from the class itself or an instance of it.
These can be used as arguments for certain requests.
-
class
mws.Products.
FeesEstimateRequest
(marketplace_id, id_type, id_value, price_to_estimate_fees, is_amazon_fulfilled, identifier)¶ A product, marketplace, and proposed price used to request estimated fees.
Instances of this model are required for the argument(s) of
get_my_fees_estimate
. Constructing an instance of this model requires the use of other data models in the Products API, as well.Example
Note
In examples below, we use the
Products
class definition to locate our models:from mws import Products Products.MoneyType(...)
You can also access the same models from any instance of the
Products
class:products_api = Products(...) products_api.MoneyType(...)
Start by creating
MoneyType
instances to account for different prices associated with the request, such aslisting_price
andshipping
:my_price = Products.MoneyType( amount=123.45, currency_code=Products.CurrencyCode.GBP, ) # Note the `currency_code` argument also accepts string literals of the currency code: my_shipping = Products.MoneyType(amount=5.00, currency_code='GBP')
Combine these prices into a
PriceToEstimateFees
instance:my_product_price = Products.PriceToEstimateFees( listing_price=my_price, shipping=my_shipping, )
For the JP market only, this price to estimate fees may optionally include
Points
.Use the
PriceToEstimateFees
instance along with other data to construct the finalFeesEstimateRequest
instance:estimate_request = Products.FeesEstimateRequest( marketplace_id=my_market, id_type="ASIN", # either 'ASIN' or 'SKU', indicating the type of the `id_value` argument: id_value="B07QR73T66", price_to_estimate_fees=my_product_price, # your `PriceToEstimateFees` instance is_amazon_fulfilled=False, identifier="request001", # a unique identifier of your choosing )
-
class
mws.Products.
PriceToEstimateFees
(listing_price, shipping, points=None)¶ Price information for a product, used to estimate fees.
Accepts instances of
MoneyType
for itslisting_price
andshipping
, and optionally accepts aPoints
instance to denote a points value (in JP region only).
-
class
mws.Products.
MoneyType
(amount, currency_code)¶ An amount of money in a specified currency.
Example
my_money = Products.MoneyType( amount=3.50, currency_code=Products.CurrencyCode.USD, )
-
class
mws.Products.
Points
(points_number, monetary_value)¶ The number of Amazon Points offered with the purchase of an item. The Amazon Points program is only available in Japan.
Points are expressed in terms of a
points_number
and amonetary_value
for those points, the latter of which must be an instance ofMoneyType
.Example:
# A monetary value of 2000 Japanese yen monetary_value = Products.MoneyType( amount=2000.0, currency_code=Products.CurrencyCode.JPY, ) # Now assign the points like so: points = Products.Points( points_number=35, monetary_value=monetary_value, )
When used in a request, points will be converted to a set of parameters like so:
print(points.to_params()) # {'PointsNumber': 35, 'PointsMonetaryValue.Amount': 2000.0, 'PointsMonetaryValue.CurrencyCode': <CurrencyCode.JPY: ('JPY', 'Japanese yen')>}
Note
You will see the
PointsMonetaryValue.CurrencyCode
element remains an instance of Enum at this stage. When used in a request, it is automatically “cleaned” to its parameterized value,'JPY'
.Passing the string literal
'JPY'
as theMoneyType.currency_code
argument is also accepted.
Enums¶
Related Enums are also attached to the Products
API class, and can be accessed the same way as Data models.
-
class
mws.Products.
CurrencyCode
(value)¶ Bases:
str
,enum.Enum
Constants for currency codes supported by Amazon.
Example:
# 10 US dollars listing_price = Products.MoneyType( amount=10.0, currency_code=Products.CurrencyCode.USD, ) print(listing_price.to_params()) # {"Amount": 10.0, "CurrencyCode": "USD"} # 30 Chinese yuan shipping = Products.MoneyType(30.0, Products.CurrencyCode.RMB) print(shipping.to_params()) # {"Amount": 30.0, "CurrencyCode": "RMB"}
-
USD
= 'USD'¶ United States dollar
-
EUR
= 'EUR'¶ European euro
-
GBP
= 'GBP'¶ Great Britain pounds
-
RMB
= 'RMB'¶ Chinese yuan
-
INR
= 'INR'¶ Indian rupee
-
JPY
= 'JPY'¶ Japanese yen
-
CAD
= 'CAD'¶ Canadian dollar
-
MXN
= 'MXN'¶ Mexican peso
-
Reports¶
According to Amazon’s documentation:
The Reports API section of the Amazon Marketplace Web Service (Amazon MWS) API lets you request various reports that help you manage your Sell on Amazon business. Report types are specified using the ReportTypes enumeration.
Reports API reference¶
-
class
mws.
Reports
(access_key, secret_key, account_id, region='US', uri='', version='', auth_token='', proxy=None, user_agent_str='', headers=None, force_response_encoding=None)[source]¶ Amazon MWS Reports API.
MWS Docs: Reports API Overview
-
request_report
(report_type, start_date=None, end_date=None, marketplace_ids=None, report_options=None)[source]¶ Creates a report request and submits the request to Amazon MWS.
- Parameters
report_type (Union[mws.models.reports.ReportType, str]) –
start_date (Union[datetime.datetime, datetime.date]) –
end_date (Union[datetime.datetime, datetime.date]) –
marketplace_ids (List[Union[mws.mws.Marketplaces, str]]) –
report_options (dict) –
-
get_report_request_list
(request_ids=None, report_types=None, processing_statuses=None, max_count=None, from_date=None, to_date=None, next_token=None)[source]¶ Returns a list of report requests that you can use to get the ReportRequestId for a report.
Pass
next_token
with no other arguments to call the GetReportRequestListByNextToken operation, requesting the next page of results.MWS Docs: GetReportRequestList
- Parameters
request_ids (List[str]) –
report_types (List[Union[mws.models.reports.ReportType, str]]) –
processing_statuses (List[Union[mws.models.reports.ProcessingStatus, str]]) –
max_count (int) –
from_date (Union[datetime.datetime, datetime.date]) –
to_date (Union[datetime.datetime, datetime.date]) –
next_token (str) –
-
get_report_request_list_by_next_token
(token)[source]¶ Alias for
get_report_request_list(next_token=token)
.MWS Docs: GetReportRequestListByNextToken
- Parameters
token (str) –
-
get_report_request_count
(report_types=None, processing_statuses=None, from_date=None, to_date=None)[source]¶ Returns a count of report requests that have been submitted to Amazon MWS for processing.
MWS Docs: GetReportRequestCount
- Parameters
report_types (List[Union[mws.models.reports.ReportType, str]]) –
processing_statuses (List[Union[mws.models.reports.ProcessingStatus, str]]) –
from_date (Union[datetime.datetime, datetime.date]) –
to_date (Union[datetime.datetime, datetime.date]) –
-
cancel_report_requests
(request_ids=None, report_types=None, processing_statuses=None, from_date=None, to_date=None)[source]¶ Cancels one or more report requests.
MWS Docs: CancelReportRequests
- Parameters
request_ids (Optional[List[str]]) –
report_types (Optional[List[Union[mws.models.reports.ReportType, str]]]) –
processing_statuses (Optional[List[Union[mws.models.reports.ProcessingStatus, str]]]) –
from_date (Optional[Union[datetime.datetime, datetime.date]]) –
to_date (Optional[Union[datetime.datetime, datetime.date]]) –
-
get_report_list
(request_ids=None, max_count=None, report_types=None, acknowledged=None, from_date=None, to_date=None, next_token=None)[source]¶ Returns a list of reports that were created between fromdate and todate (defaults to previous 90 days if ommitted).
Pass
next_token
with no other arguments to call the GetReportListByNextToken operation, requesting the next page of results.- Parameters
request_ids (List[str]) –
max_count (int) –
report_types (List[Union[mws.models.reports.ReportType, str]]) –
acknowledged (bool) –
from_date (Union[datetime.datetime, datetime.date]) –
to_date (Union[datetime.datetime, datetime.date]) –
next_token (str) –
-
get_report_list_by_next_token
(token)[source]¶ Alias for
get_report_list(next_token=token)
.MWS Docs: GetReportListByNextToken
- Parameters
token (str) –
-
get_report_count
(report_types=None, acknowledged=None, from_date=None, to_date=None)[source]¶ Returns a count of the reports, created in the previous 90 days, with a status of _DONE_ and that are available for download.
- Parameters
report_types (List[Union[mws.models.reports.ReportType, str]]) –
acknowledged (bool) –
from_date (Union[datetime.datetime, datetime.date]) –
to_date (Union[datetime.datetime, datetime.date]) –
-
get_report
(report_id)[source]¶ Returns the contents of a report and the Content-MD5 header for the returned report body.
- Parameters
report_id (str) –
-
manage_report_schedule
(report_type, schedule, schedule_date=None)[source]¶ Creates, updates, or deletes a report request schedule for a specified report type.
MWS Docs: ManageReportSchedule
- Parameters
report_type (mws.models.reports.ReportType) –
schedule (mws.models.reports.Schedule) –
schedule_date (Optional[Union[datetime.datetime, datetime.date]]) –
-
get_report_schedule_list
(report_types=None, next_token=None)[source]¶ Returns a list of order report requests that are scheduled to be submitted to Amazon MWS for processing.
Pass
next_token
with no other arguments to call the GetReportScheduleListByNextToken operation, requesting the next page of results.MWS Docs: GetReportScheduleList
- Parameters
report_types (List[Union[mws.models.reports.ReportType, str]]) –
next_token (str) –
-
get_report_schedule_list_by_next_token
(token)[source]¶ Alias for
get_report_schedule_list(next_token=token)
.MWS Docs: GetReportScheduleListByNextToken
- Parameters
token (str) –
-
get_report_schedule_count
(report_types=None)[source]¶ Returns a count of order report requests that are scheduled to be submitted to Amazon MWS.
MWS Docs: GetReportScheduleCount
- Parameters
report_types (List[Union[mws.models.reports.ReportType, str]]) –
-
update_report_acknowledgements
(report_ids=None, acknowledged=None)[source]¶ Updates the acknowledged status of one or more reports.
MWS Docs: UpdateReportAcknowledgements
- Parameters
report_ids (Optional[List[str]]) –
acknowledged (Optional[bool]) –
-
Enums¶
-
class
mws.Reports.
ReportType
(value)¶ Bases:
str
,enum.Enum
An enumeration of the types of reports that can be requested from Amazon MWS.
MWS Docs: ReportType enumeration
Available values
You can use either the Enum instance itself or its string value as an argument in relevant request methods. Each of the below examples may be used in a request for a flat file of open listings:
from mws import Reports my_report_type = Reports.ReportType.INVENTORY # OR my_report_type = Reports.ReportType.INVENTORY.value # OR my_report_type = '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_'
-
INVENTORY
= '_GET_FLAT_FILE_OPEN_LISTINGS_DATA_'¶
-
ALL_LISTINGS
= '_GET_MERCHANT_LISTINGS_ALL_DATA_'¶
-
ACTIVE_LISTINGS
= '_GET_MERCHANT_LISTINGS_DATA_'¶
-
INACTIVE_LISTINGS
= '_GET_MERCHANT_LISTINGS_INACTIVE_DATA_'¶
-
OPEN_LISTINGS
= '_GET_MERCHANT_LISTINGS_DATA_BACK_COMPAT_'¶
-
OPEN_LISTINGS_LITE
= '_GET_MERCHANT_LISTINGS_DATA_LITE_'¶
-
OPEN_LISTINGS_LITER
= '_GET_MERCHANT_LISTINGS_DATA_LITER_'¶
-
CANCELED_LISTINGS
= '_GET_MERCHANT_CANCELLED_LISTINGS_DATA_'¶
-
SOLD_LISTINGS
= '_GET_CONVERGED_FLAT_FILE_SOLD_LISTINGS_DATA_'¶
-
LISTING_QUALITY_AND_SUPPRESSED
= '_GET_MERCHANT_LISTINGS_DEFECT_DATA_'¶
-
PAN_EUROPEAN_ELIGIBILITY_FBA_ASINS
= '_GET_PAN_EU_OFFER_STATUS_'¶
-
PAN_EUROPEAN_ELIGIBILITY_SELF_FULFILLED_ASINS
= '_GET_MFN_PAN_EU_OFFER_STATUS_'¶
-
GLOBAL_EXPANSION_OPPORTUNITIES
= '_GET_FLAT_FILE_GEO_OPPORTUNITIES_'¶
-
REFERRAL_FEE_PREVIEW
= '_GET_REFERRAL_FEE_PREVIEW_REPORT_'¶
-
ORDERS_UNSHIPPED
= '_GET_FLAT_FILE_ACTIONABLE_ORDER_DATA_'¶
-
ORDERS_SCHEDULED_XML
= '_GET_ORDERS_DATA_'¶
-
ORDERS_REQUESTED_OR_SCHEDULED
= '_GET_FLAT_FILE_ORDERS_DATA_'¶
-
ORDERS_CONVERGED
= '_GET_CONVERGED_FLAT_FILE_ORDER_REPORT_DATA_'¶
-
TRACKING_BY_LAST_UPDATE
= '_GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE_'¶
-
TRACKING_BY_ORDER_DATE
= '_GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_'¶
-
TRACKING_ARCHIVED_ORDERS_FLATFILE
= '_GET_FLAT_FILE_ARCHIVED_ORDERS_DATA_BY_ORDER_DATE_'¶
-
TRACKING_BY_LAST_UPDATE_XML
= '_GET_XML_ALL_ORDERS_DATA_BY_LAST_UPDATE_'¶
-
TRACKING_BY_ORDER_DATE_XML
= '_GET_XML_ALL_ORDERS_DATA_BY_ORDER_DATE_'¶
-
PENDING_ORDERS_FLAT_FILE
= '_GET_FLAT_FILE_PENDING_ORDERS_DATA_'¶
-
PENDING_ORDERS_XML
= '_GET_PENDING_ORDERS_DATA_'¶
-
PENDING_ORDERS_CONVERGED_FLAT_FILE
= '_GET_CONVERGED_FLAT_FILE_PENDING_ORDERS_DATA_'¶
-
RETURNS_XML_DATA_BY_RETURN_DATE
= '_GET_XML_RETURNS_DATA_BY_RETURN_DATE_'¶
-
RETURNS_FLAT_FILE_RETURNS_DATA_BY_RETURN_DATE
= '_GET_FLAT_FILE_RETURNS_DATA_BY_RETURN_DATE_'¶
-
RETURNS_XML_MFN_PRIME_RETURNS_REPORT
= '_GET_XML_MFN_PRIME_RETURNS_REPORT_'¶
-
RETURNS_CSV_MFN_PRIME_RETURNS_REPORT
= '_GET_CSV_MFN_PRIME_RETURNS_REPORT_'¶
-
RETURNS_XML_MFN_SKU_RETURN_ATTRIBUTES_REPORT
= '_GET_XML_MFN_SKU_RETURN_ATTRIBUTES_REPORT_'¶
-
RETURNS_FLAT_FILE_MFN_SKU_RETURN_ATTRIBUTES_REPORT
= '_GET_FLAT_FILE_MFN_SKU_RETURN_ATTRIBUTES_REPORT_'¶
-
PERFORMANCE_FEEDBACK
= '_GET_SELLER_FEEDBACK_DATA_'¶
-
PERFORMANCE_CUSTOMER_METRICS_XML
= '_GET_V1_SELLER_PERFORMANCE_REPORT_'¶
-
SETTLEMENT_FLATFILE
= '_GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_'¶
-
SETTLEMENT_V2_XML
= '_GET_V2_SETTLEMENT_REPORT_DATA_XML_'¶
-
SETTLEMENT_V2_FLATFILE
= '_GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_V2_'¶
-
FBA_SALES_AMAZON_FULFILLED
= '_GET_AMAZON_FULFILLED_SHIPMENTS_DATA_'¶
-
FBA_SALES_ALL_LAST_UPDATE
= '_GET_FLAT_FILE_ALL_ORDERS_DATA_BY_LAST_UPDATE_'¶
-
FBA_SALES_ALL_BY_ORDER_DATE
= '_GET_FLAT_FILE_ALL_ORDERS_DATA_BY_ORDER_DATE_'¶
-
FBA_SALES_ALL_BY_LAST_UPDATE_XML
= '_GET_XML_ALL_ORDERS_DATA_BY_LAST_UPDATE_'¶
-
FBA_SALES_ALL_BY_ORDER_DATE_XML
= '_GET_XML_ALL_ORDERS_DATA_BY_ORDER_DATE_'¶
-
FBA_SALES_CUSTOMER_SHIPMENT
= '_GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_SALES_DATA_'¶
-
FBA_SALES_PROMOTIONS
= '_GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_PROMOTION_DATA_'¶
-
FBA_SALES_CUSTOMER_TAXES
= '_GET_FBA_FULFILLMENT_CUSTOMER_TAXES_DATA_'¶
-
FBA_SALES_REMOTE_FULFILLMENT_ELIGIBILITY
= '_GET_REMOTE_FULFILLMENT_ELIGIBILITY_'¶
-
FBA_INVENTORY_AFN
= '_GET_AFN_INVENTORY_DATA_'¶
-
FBA_INVENTORY_AFN_BY_COUNTRY
= '_GET_AFN_INVENTORY_DATA_BY_COUNTRY_'¶
-
FBA_INVENTORY_HISTORY_DAILY
= '_GET_FBA_FULFILLMENT_CURRENT_INVENTORY_DATA_'¶
-
FBA_INVENTORY_HISTORY_MONTHLY
= '_GET_FBA_FULFILLMENT_MONTHLY_INVENTORY_DATA_'¶
-
FBA_INVENTORY_RECEIVED
= '_GET_FBA_FULFILLMENT_INVENTORY_RECEIPTS_DATA_'¶
-
FBA_INVENTORY_RESERVED
= '_GET_RESERVED_INVENTORY_DATA_'¶
-
FBA_INVENTORY_EVENT_DETAIL
= '_GET_FBA_FULFILLMENT_INVENTORY_SUMMARY_DATA_'¶
-
FBA_INVENTORY_ADJUSTMENTS
= '_GET_FBA_FULFILLMENT_INVENTORY_ADJUSTMENTS_DATA_'¶
-
FBA_INVENTORY_HEALTH
= '_GET_FBA_FULFILLMENT_INVENTORY_HEALTH_DATA_'¶
-
FBA_INVENTORY_MANAGE_ACTIVE
= '_GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA_'¶
-
FBA_INVENTORY_MANAGE_ALL
= '_GET_FBA_MYI_ALL_INVENTORY_DATA_'¶
-
FBA_INVENTORY_RESTOCK_INVENTORY
= '_GET_RESTOCK_INVENTORY_RECOMMENDATIONS_REPORT_'¶
-
FBA_INVENTORY_CROSS_BORDER_MOVEMENT
= '_GET_FBA_FULFILLMENT_CROSS_BORDER_INVENTORY_MOVEMENT_DATA_'¶
-
FBA_INVENTORY_INBOUND_PERFORMANCE
= '_GET_FBA_FULFILLMENT_INBOUND_NONCOMPLIANCE_DATA_'¶
-
FBA_INVENTORY_STRANDED
= '_GET_STRANDED_INVENTORY_UI_DATA_'¶
-
FBA_INVENTORY_BULK_FIX_STRANDED
= '_GET_STRANDED_INVENTORY_LOADER_DATA_'¶
-
FBA_INVENTORY_AGE
= '_GET_FBA_INVENTORY_AGED_DATA_'¶
-
FBA_INVENTORY_EXCESS
= '_GET_EXCESS_INVENTORY_DATA_'¶
-
FBA_INVENTORY_STORAGE_FEE_CHARGES
= '_GET_FBA_STORAGE_FEE_CHARGES_DATA_'¶
-
FBA_INVENTORY_PRODUCT_EXCHANGE
= '_GET_PRODUCT_EXCHANGE_DATA_'¶
-
FBA_PAYMENTS_FEE_PREVIEW
= '_GET_FBA_ESTIMATED_FBA_FEES_TXT_DATA_'¶
-
FBA_PAYMENTS_REIMBURSEMENTS
= '_GET_FBA_REIMBURSEMENTS_DATA_'¶
-
FBA_PAYMENTS_LONGTERM_STORAGE_FEE_CHARGES
= '_GET_FBA_FULFILLMENT_LONGTERM_STORAGE_FEE_CHARGES_DATA_'¶
-
FBA_CONCESSION_RETURNS
= '_GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA_'¶
-
FBA_CONCESSION_SHIPMENT_REPLACEMENT
= '_GET_FBA_FULFILLMENT_CUSTOMER_SHIPMENT_REPLACEMENT_DATA_'¶
-
FBA_REMOVAL_RECOMMENDED
= '_GET_FBA_RECOMMENDED_REMOVAL_DATA_'¶
-
FBA_REMOVAL_ORDER_DETAIL
= '_GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA_'¶
-
FBA_REMOVAL_SHIPMENT_DETAIL
= '_GET_FBA_FULFILLMENT_REMOVAL_SHIPMENT_DETAIL_DATA_'¶
-
FBA_SMALL_LIGHT_INVENTORY
= '_GET_FBA_UNO_INVENTORY_DATA_'¶
-
SALES_TAX
= '_GET_FLAT_FILE_SALES_TAX_DATA_'¶
-
VAT_CALCULATION
= '_SC_VAT_TAX_REPORT_'¶
-
VAT_TRANSACTIONS
= '_GET_VAT_TRANSACTION_DATA_'¶
-
TAX_GST_MERCHANT_B2B
= '_GET_GST_MTR_B2B_CUSTOM_'¶
-
TAX_GST_MERCHANT_B2C
= '_GET_GST_MTR_B2C_CUSTOM_'¶
-
BROWSE_TREE
= '_GET_XML_BROWSE_TREE_DATA_'¶
-
EASYSHIP_DOCUMENTS
= '_GET_EASYSHIP_DOCUMENTS_'¶
-
EASYSHIP_PICKED_UP
= '_GET_EASYSHIP_PICKEDUP_'¶
-
EASYSHIP_WAITING_FOR_PICKUP
= '_GET_EASYSHIP_WAITING_FOR_PICKUP_'¶
-
AMZN_BUSINESS_FEE_DISCOUNTS_REPORT
= '_FEE_DISCOUNTS_REPORT_'¶
-
AMZN_BUSINESS_RFQD_BULK_DOWNLOAD
= '_RFQD_BULK_DOWNLOAD_'¶
-
AMAZONPAY_SANDBOX_SETTLEMENT
= '_GET_FLAT_FILE_OFFAMAZONPAYMENTS_SANDBOX_SETTLEMENT_DATA_'¶
-
-
class
mws.Reports.
Schedule
(value)¶ Bases:
str
,enum.Enum
An enumeration of the units of time that reports can be requested.
MWS Docs: Schedule enumeration
Available values
Several schedule frequencies are provided by Amazon, and this Enum provides easy access to all of them through several aliases for each schedule type.
-
EVERY_15_MIN
= '_15_MINUTES_'¶
-
EVERY_15_MINS
= '_15_MINUTES_'¶
-
EVERY_15_MINUTE
= '_15_MINUTES_'¶
-
EVERY_15_MINUTES
= '_15_MINUTES_'¶
-
EVERY_30_MIN
= '_30_MINUTES_'¶
-
EVERY_30_MINS
= '_30_MINUTES_'¶
-
EVERY_30_MINUTE
= '_30_MINUTES_'¶
-
EVERY_30_MINUTES
= '_30_MINUTES_'¶
-
EVERY_HOUR
= '_1_HOUR_'¶
-
EVERY_1_HOUR
= '_1_HOUR_'¶
-
EVERY_1_HOURS
= '_1_HOUR_'¶
-
EVERY_2_HOUR
= '_2_HOURS_'¶
-
EVERY_2_HOURS
= '_2_HOURS_'¶
-
EVERY_4_HOUR
= '_4_HOURS_'¶
-
EVERY_4_HOURS
= '_4_HOURS_'¶
-
EVERY_8_HOUR
= '_8_HOURS_'¶
-
EVERY_8_HOURS
= '_8_HOURS_'¶
-
EVERY_12_HOUR
= '_12_HOURS_'¶
-
EVERY_12_HOURS
= '_12_HOURS_'¶
-
DAILY
= '_1_DAY_'¶
-
EVERY_DAY
= '_1_DAY_'¶
-
EVERY_1_DAY
= '_1_DAY_'¶
-
EVERY_1_DAYS
= '_1_DAY_'¶
-
EVERY_2_DAY
= '_2_DAYS_'¶
-
EVERY_2_DAYS
= '_2_DAYS_'¶
-
EVERY_48_HOUR
= '_2_DAYS_'¶
-
EVERY_48_HOURS
= '_2_DAYS_'¶
-
EVERY_3_DAY
= '_72_HOURS_'¶
-
EVERY_3_DAYS
= '_72_HOURS_'¶
-
EVERY_72_HOUR
= '_72_HOURS_'¶
-
EVERY_72_HOURS
= '_72_HOURS_'¶
-
WEEKLY
= '_1_WEEK_'¶
-
EVERY_WEEK
= '_1_WEEK_'¶
-
EVERY_1_WEEK
= '_1_WEEK_'¶
-
EVERY_1_WEEKS
= '_1_WEEK_'¶
-
EVERY_7_DAY
= '_1_WEEK_'¶
-
EVERY_7_DAYS
= '_1_WEEK_'¶
-
EVERY_14_DAY
= '_14_DAYS_'¶
-
EVERY_14_DAYS
= '_14_DAYS_'¶
-
EVERY_2_WEEK
= '_14_DAYS_'¶
-
EVERY_2_WEEKS
= '_14_DAYS_'¶
-
FORTNIGHTLY
= '_14_DAYS_'¶
-
EVERY_15_DAY
= '_15_DAYS_'¶
-
EVERY_15_DAYS
= '_15_DAYS_'¶
-
EVERY_30_DAY
= '_30_DAYS_'¶
-
EVERY_30_DAYS
= '_30_DAYS_'¶
-
DELETE
= '_NEVER_'¶ Delete a previously created report request schedule.
-
-
class
mws.Reports.
ProcessingStatus
(value)¶ Bases:
str
,enum.Enum
An optional enumeration of common processing_status values.
-
SUBMITTED
= '_SUBMITTED_'¶
-
IN_PROGRESS
= '_IN_PROGRESS_'¶
-
CANCELLED
= '_CANCELLED_'¶
-
CANCELED
= '_CANCELLED_'¶ An alias for “CANCELLED”, as some folks spell it with one L and there’s nothing wrong with that.
-
DONE
= '_DONE_'¶
-
DONE_NO_DATA
= '_DONE_NO_DATA_'¶
-
DotDict¶
New in version 1.0dev15: DotDict
added.
Warning
The following pertains to features added in v1.0dev15 related to MWS requests.
These features are disabled by default. To use these features, set flag _use_feature_mwsresponse
to True
on an API class instance before making any requests:
api_class = Orders(...)
api_class._use_feature_mwsresponse = True
If the flag is False
, all requests will return either DictWrapper
or DataWrapper
objects (deprecated);
and parsed XML contents will be returned as an instance of ObjectDict
(deprecated).
New features using MWSResponse
and DotDict
will become the default in v1.0.
The DotDict
class is a subclass of a standard Python dict that provides
access to its keys as attributes. This object is used mainly for parsed XML content returned by
MWSResponse.parsed
and
MWSResponse.metadata
, but DotDict
can also be used as a
general-purpose dict
replacement (with some caveats, as shown below).
Keys as attributes¶
While keys of a DotDict
can be accessed the same as keys in a standard dict
, they can also be accessed
as attributes:
from mws.utils.collections import DotDict
foo = DotDict({'spam': 'ham'})
print(foo['spam'])
# 'ham'
print(foo.spam)
# 'ham'
print(foo.get('spam'))
# 'ham'
This is useful for traversing the nested structures created by parsing XML documents, where several keys are required in order to access a leaf node.
Consider the following (truncated and edited) example response from the MWS operation ListMatchingProducts
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0"?>
<ListMatchingProductsResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<ListMatchingProductsResult>
<Products>
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ACBDEFGH</MarketplaceId>
<ASIN>B0987654</ASIN>
</MarketplaceASIN>
</Identifiers>
</Product>
</Products>
</ListMatchingProductsResult>
</ListMatchingProductsResponse>
|
When this document is parsed, accessing the <ASIN>
on line 9 using dict keys looks like the following:
# assuming `response` is an instance of `MWSResponse`
asin = response.parsed['Products']['Product']['Identifiers']['MarketplaceASIN']['ASIN']
Using attribute access, the above call turns into:
asin = response.parsed.Products.Product.Identifiers.MarketplaceASIN.ASIN
And, of course, a mix of the different methods is possible:
asin = response.parsed['Products'].get('Product').Identifiers['MarketplaceASIN'].get('ASIN')
Tip
Accessing specific data in an MWS response will often produce lengthy code lines, as the above samples show. We recommend following best practices for Python programs in general, breaking up these longer lines by assigning chunks of data to intermediary variables:
product = response.parsed.Products.Product
asin = product.Identifiers.MarketplaceASIN.ASIN
Native iteration¶
XML represents sequences of similar objects by having sibling tags with the same tag name. Consider the following
toy example with three <Product>
tags:
<Response>
<Products>
<Product>
<Name>spam</Name>
</Product>
<Product>
<Name>ham</Name>
</Product>
<Product>
<Name>eggs</Name>
</Product>
</Products>
</Response>
When parsed, these are collected into a list of DotDict
instances:
DotDict({
'Products': DotDict({
'Product': [
DotDict({'Name': 'spam'}),
DotDict({'Name': 'ham'}),
DotDict({'Name': 'eggs'}),
]
})
})
Note
The list of objects will always be found under the same key name as the duplicate tags, i.e. Product
;
not under their parent key, Products
. This may seem counterintuitive, but the parser is simply preserving all
tag names present in the XML document.
Further, if a tag attribute is present on the parent <Products>
tag, you would be able to access it as a
separate key at the same level as Product
. This would not be possible if Products
returned a list.
To gather the names of all products in this response, we can simply iterate over this list:
names = []
for product in response.parsed.Products.Product:
names.append(product.Name)
print(names)
# ['spam', 'ham', 'eggs']
If the same request returns only one <Product>
tag, the Product
key in the parsed response will return only
a single DotDict
, similar to any other node in the XML tree. Trying to access the Product
node in this case
as though it were a list - such as using indices (.Product[0]
) - will result in errors.
However, when a DotDict
is iterated, it will wrap itself in a list in order to provide the same interface as before.
So, for an XML response like so:
<Response>
<Products>
<Product>
<Name>foo</Name>
</Product>
</Products>
</Response>
…the same Python code can be used to access “all” Product
keys:
names = []
for product in response.parsed.Products.Product:
names.append(product.Name)
print(names)
# ['foo']
Note
While DotDict
is a subclass of dict
, this behavior is different from that of the standard dict
,
where iterating directly on the dict
object is equivalent to iterating on dict.keys()
. We have chosen to
implement the above behavior to more closely match most users’ intended usage when working with parsed XML,
even though DotDict
can be used much like a standard dict
for (most) general purposes.
Recursive conversion of dict objects¶
DotDict
instances expect to hold nested data, as seen in the examples throughout this document. As such, any
dict
assigned as a value to a DotDict
is automatically converted to a DotDict
, as well. The values
of the assigned dict
are then recursively built the same way, such that every dict
(or other mapping type)
instance in the structure is also converted to DotDict
.
This holds true in a variety of scenarios:
Wrapping a nested
dict
inDotDict
:example1 = DotDict({'spam': {'ham': {'eggs': 'juice'}}}) print(example1) # DotDict({'spam': DotDict({'ham': DotDict({'eggs': 'juice'})})})
Using kwargs to build
DotDict
, with adict
as one of the values:example2 = DotDict(spam={'muffin': {'cereal': 'milk'}}) print(example2) DotDict({'spam': DotDict({'muffin': DotDict({'cereal': 'milk'})})})
Assigning a
dict
to a key of an existingDotDict
, including creating new keys:example3 = DotDict() example3.pancakes = {'maple': 'syrup'} print(example3) # DotDict({'pancakes': DotDict({'maple': 'syrup'})}) example3.pancakes.toast = {'strawberry': 'jam'} print(example3) # DotDict({'pancakes': DotDict({'maple': 'syrup', 'toast': DotDict({'strawberry': 'jam'})})})
Using
DotDict.update
in a similar manner asdict.update
:example4 = DotDict() example4.update({'chicken': {'waffles': 'honey'}}) print(example4) # DotDict({'chicken': DotDict({'waffles': 'honey'})}) # Including a mix of a plain dict and kwargs example5 = DotDict() example5.update({'running': {'out': 'of'}}, food='examples', to={'use': 'here'}) print(example5) # DotDict({'running': DotDict({'out': 'of'}), 'food': 'examples', 'to': DotDict({'use': 'here'})})
Working with XML tag attributes¶
DotDict
is used in python-amazon-mws primarily for parsed XML content. As such, some features of the class are
specialized for working with that content.
XML tags can contain attributes with additional data points. When parsed, these attributes are assigned to their own
dict keys starting with @
, differentiating them from normal tag names.
Further, tags that contain an attribute and text content will store the text on a special key, #text
.
For example, with the following XML document:
<Response>
<Products>
<Product Name="spam">
<SomethingElse>ham</SomethingElse>
<WhatHaveYou anotherAttr="foo">eggs</WhatHaveYou>
</Product>
</Products>
</Response>
The parsed response would look like:
DotDict({
'Products': DotDict({
'Product': DotDict({
'@Name': 'spam',
'SomethingElse': 'ham',
'WhatHaveYou': DotDict({
'@anotherAttr': 'foo',
'#text': 'eggs'
})
})
})
})
These @
and #text
keys cannot be accessed directly as attributes due to Python syntax, which reserves the
@
and #
characters. You can still use standard dict keys to access this content:
print(dotdict.Products.Product['@Name'])
# 'spam'
print(dotdict.Products.Product.WhatHaveYou['#text'])
# 'eggs'
DotDict
also allows accessing these keys using a fallback method. Simply provide the key name without
@
or #
in front, and it will attempt to find a matching key:
print(dotdict.Products.Product.Name)
# 'spam'
print(dotdict.Products.Product.WhatHaveYou.text)
# 'eggs'
Note
In case of a conflicting key name, a key matching the attribute will be returned first:
dotdict = DotDict({'foo': 'spam', '@foo': 'ham'})
print(dotdict.foo)
# 'spam'
print(dotdict['@foo'])
# 'ham'
This conflict is a rare occurrence for most XML documents, however, as they are not likely to return a tag attribute with the same name as an immediate child tag.
DotDict API¶
-
class
mws.
DotDict
(*args, **kwargs)[source]¶ Read-only dict-like object class that wraps a mapping object.
New in version 1.0dev15.
-
update
(*args, **kwargs)[source]¶ Recursively builds values in any nested objects, such that any mapping object in the nested structure is converted to a
DotDict
.Each nested mapping object will be converted to
DotDict
.Each non-string, non-dict iterable will have elements built, as well.
All other objects in the data are left unchanged.
-
MWSResponse¶
New in version 1.0dev15: MWSResponse
added
Warning
The following pertains to features added in v1.0dev15 related to MWS requests.
These features are disabled by default. To use these features, set flag _use_feature_mwsresponse
to True
on an API class instance before making any requests:
api_class = Orders(...)
api_class._use_feature_mwsresponse = True
If the flag is False
, all requests will return either DictWrapper
or DataWrapper
objects (deprecated);
and parsed XML contents will be returned as an instance of ObjectDict
(deprecated).
New features using MWSResponse
and DotDict
will become the default in v1.0.
MWSResponse
acts as a wrapper for requests.Response
objects returned from requests made to MWS.
When initialized, the response content is automatically parsed for XML content,
making it available as a DotDict
instance in MWSResponse.parsed
.
Parsed content for XML responses¶
All XML response content is automatically parsed using the xmltodict
package. The parsed results are stored as a
DotDict
accessible from
MWSResponse.parsed
.
For more details on working with the parsed content, please see DotDict.
Original response access¶
As MWSResponse
wraps a requests.Response
object, all data and methods of that underlying object can be accessed
from the MWSResponse
instance using one of the following:
The
MWSResponse.original
attribute:response = api.foo_request(...) # response is an instance of MWSResponse response.original.status_code # 200 response.original.headers # {'Content-Type': ...} response.original.text # unicode # 'Hello world!' response.original.content # bytes # b'Hello world!'
A number of shortcut properties available on
MWSResponse
itself:response.content # response.original.content response.cookies # response.original.cookies response.elapsed # response.original.elapsed response.encoding # response.original.encoding response.headers # response.original.headers response.reason # response.original.reason response.request # response.original.request response.status_code # response.original.status_code response.text # response.original.text
Each of these shortcuts is a read-only property, with the exception of
response.encoding
, which includes a setter for convenience when dealing with content encoding issues:response.encoding = "iso-8859-1" print(response.original.encoding) # "iso-8859-1"
MWSResponse API¶
New in version 1.0dev15.
-
class
mws.
MWSResponse
(response, result_key=None, encoding=None, force_cdata=False)[source]¶ Wraps a
requests.Response
object and extracts some known data.Particularly for XML responses, parsed contents can be found in the
.parsed
property as aDotDict
instance.Find metadata in
.metadata
, mainly for accessing.metadata.RequestId
; or simply use the.request_id
shortcut attr.- Parameters
response (request.Response) – Response object returned by a request sent to MWS.
result_key (str) – Key to use as the root for
.parsed
. Typically a tag in the root of the response’s XML document whose name ends inResult
. Defaults toNone
, in which case the full document is presented when using.parsed
.force_cdata (bool) – Passed to
xmltodict.parse()
when parsing the response’s XML document. Defaults toFalse
.
-
original
: requests.Response¶ Instance of the original
requests.Response
object. Can be used to get or set data in the original response.
-
property
encoding
¶ Shortcut to
.original.encoding
. Can also be used as a setter, changing the encoding of the response. This then changes how content is decoded when using.text
.
-
parse_response
(force_cdata=False)[source]¶ Runs
.text
throughxmltodict.parse()
, storing the returned Python dictionary as._dict
.If no XML errors occur during that process, constructs
DotDict
instances from the parsed XML data, making them available from.parsed
and.metadata
.For non-XML responses, does nothing.
- Parameters
force_cdata (bool) – Passed to
xml_to_dict.parse()
when parsing XML content. Defaults toFalse
. Ignored for non-XML responses.
-
property
parsed
¶ Returns a parsed version of the response.
For XML documents, returns a
DotDict
of the parsed XML content, starting from._result_key
.For all other types of responses, returns
.text
instead.
-
property
metadata
¶ Returns a
DotDict
instance from the response’sResponseMetadata
key, if present. Typically the only key of note here is.metadata.RequestId
, which can also be accessed with.request_id
.
-
property
content
¶ Shortcut to
.original.content
, which is bytes.
Shortcut to
.original.cookies
.
-
property
elapsed
¶ Shortcut to
.original.elapsed
.
-
property
headers
¶ Shortcut to
.original.headers
.
-
property
reason
¶ Shortcut to
.original.reason
.
-
property
request
¶ Shortcut to
.original.request
.
-
property
status_code
¶ Shortcut to
.original.status_code
.
-
property
text
¶ Shortcut to
.original.text
, which is unicode.