python-amazon-sp-api

repository·master·Indexed 20 days ago

https://github.com/saleweaver/python-amazon-sp-api

A Python wrapper for Amazon's Selling Partner API (SP-API) providing synchronous and asynchronous (asyncio) interfaces for marketplace automation. It includes clients for Orders, Reports, Feeds, and Data Kiosk APIs, with support for Restricted Data Tokens (RDT), grantless operations, and AWS Secret Manager integration. The library features built-in utilities for throttling, retries, and pagination, and includes a tool to generate new API endpoints from Amazon SP-API JSON models.

Tokens
36.7K
Snippets
122
Records
158
Agent score
70%

What's inside python-amazon-sp-api

  1. Understand the PYTHON-AMAZON-SP-API architecture

    master

    The library is organized into several functional layers:

    • sp_api.api: The primary entry point for most users. It contains specific client classes for different SP-API groups (e.g., Orders, Reports, Feeds, DataKiosk).
    • sp_api.base: The core engine containing the Client base class, response wrappers (ApiResponse), marketplace definitions, credentials handling, and exceptions.
    • sp_api.util: A collection of utilities for handling common API challenges like throttling, retries, and pagination.

    Most developers interact only with the classes in sp_api.api.

  2. How auto-pagination and throttling retries work

    master

    Amazon SP-API uses tokens (like NextToken) for pagination and enforces strict rate limits. This library provides utility decorators in sp_api.util to handle these automatically:

    • @load_all_pages(): A decorator that turns an endpoint call into a generator. It automatically follows pagination tokens and yields one ApiResponse per page. If an endpoint uses a token name other than NextToken (e.g., next_token), use the next_token_param argument.
    • @throttle_retry(): A decorator that catches sp_api.base.SellingApiRequestThrottledException (HTTP 429) and retries the request.

    You can combine these decorators to create robust, paginated iterators.

    from datetime import datetime, timedelta, timezone
    from sp_api.api import Orders
    from sp_api.util import throttle_retry, load_all_pages
    
    @throttle_retry()      # retry on throttling
    @load_all_pages()      # follow NextToken automatically
    def iter_orders(**kwargs):
        return Orders().get_orders(**kwargs)
    
    for page in iter_orders(
        LastUpdatedAfter=(datetime.now(timezone.utc) - timedelta(days=7)).isoformat()
    ):
        for order in page.payload.get('Orders', []):
            print(order['AmazonOrderId'], order['OrderStatus'])
  3. Use Restricted Data Tokens (RDT) and Grantless operations

    master

    The library supports two specialized authentication modes:

    1. Restricted Data Token (RDT): For operations requiring PII (Personally Identifiable Information), pass the restricted_data_token argument to the client. This token is used in place of the standard access token.
    2. Grantless Operations: Some operations do not require seller-level authorization but require a specific scope. These are handled internally via Client._request_grantless_operation using a grantless_scope defined by the endpoint.
  4. How to handle API responses

    master

    All successful API responses are wrapped in an sp_api.base.ApiResponse object. This object provides several convenient ways to access data:

    • .payload: The original parsed JSON body.
    • __call__(): A shorthand to get the payload (e.g., response()).
    • __getattr__(): Allows accessing JSON keys directly as attributes (e.g., response.some_key).
    • .headers: Access HTTP headers (useful for checking rate limit info).
    • .errors: Contains error details if present.
    • .nextToken / .pagination: Contains tokens for paginated results.

    If the API returns an error (e.g., a 4xx or 5xx status), the library raises a specific SellingApiException subclass based on the HTTP status code.

  5. Handle pagination in GetReportsResponse

    master

    When calling the getReports endpoint, the response may include a next_token. If next_token is present, it indicates that the number of results exceeds the pageSize. To retrieve the next page of results, you must call getReports again, passing the next_token as the only parameter.

    # Conceptual usage for pagination
    # 1. Initial call
    response = client.get_reports(pageSize=100)
    
    # 2. Check for next_token and fetch next page
    if response.next_token:
        next_page = client.get_reports(next_token=response.next_token)
  6. Use async clients for asyncio-based applications

    master

    The library provides asynchronous counterparts for most API clients located in sp_api.asyncio. These clients are designed for use with asyncio and are safe for concurrent execution within event loops. Async clients are located in sp_api.asyncio.api and use the same constructor signatures as their synchronous counterparts.

    from sp_api.asyncio.api import Orders, Reports
  7. Handle API responses with ApiResponse

    master

    All endpoints in the library return an instance of sp_api.base.ApiResponse. The core data returned by Amazon is stored in the payload attribute. The ApiResponse class provides several convenient ways to access this data:

    1. Direct Access: Use response.payload to get the original response data.
    2. Attribute Access (__getattr__): Access top-level keys from the payload as if they were attributes of the response object (e.g., response.Orders).
    3. Call Access (__call__): Call the response object with a string key to retrieve the corresponding payload property (e.g., response('Orders')).
    4. Shorthand Call: Calling the response object without arguments response() is a shorthand for response.payload.
    response = Orders().get_orders(CreatedAfter='TEST_CASE_200', MarketplaceIds=["ATVPDKIKX0DER"])
    
    print(response.payload) # original response data
    # Access one of `payload`s properties using `__getattr__`
    print(response.Orders) # Array of orders
    # Access one of `payload`s properties using `__call__`
    print(response('Orders')) # Array of orders
    # Shorthand for response.payload
    print(response()) # original response data
  8. How the Client lifecycle works

    master

    When you instantiate an endpoint client (e.g., Orders()), the library performs the following steps automatically:

    1. Credential Resolution: Uses CredentialProvider to look up credentials in order: code arguments $\rightarrow$ environment variables $\rightarrow$ configuration file.
    2. Marketplace Selection: Determines the marketplace from the marketplace argument or the SP_API_DEFAULT_MARKETPLACE environment variable.
    3. Authentication: Creates an AccessTokenClient for the account.
    4. Endpoint Preparation: Configures the base URL, marketplace ID, and region.
    5. Request Execution: Passes the method, path, parameters, and body to the internal Client._request method.
    from sp_api.api import Orders
    
    # This triggers the internal lifecycle: credential resolution, 
    # marketplace selection, and auth setup.
    client = Orders()
  9. Use the load_all_pages decorator for FulfillmentInbound endpoints

    master

    When working with FulfillmentInbound endpoints that use pagination, you can use the @load_all_pages decorator to automatically fetch all available pages of data. For these specific endpoints, you must pass extras=dict(QueryType='NEXT_TOKEN') to the decorator to ensure it correctly identifies the pagination token.

    @load_all_pages(extras=dict(QueryType='NEXT_TOKEN'))
  10. Configure credentials for python-amazon-sp-api

    master

    You can provide credentials to the library using one of three methods. The library searches for credentials in the following order of precedence:

    1. Parameters passed directly in code: Highest priority.
    2. Environment variables: Used if no parameters are passed in code.
    3. Config File: Used as a fallback if neither code parameters nor environment variables are found.

    For instructions on how to obtain the required Amazon Selling Partner API credentials (IAM policies, entities, etc.), refer to the official Amazon Developer Guide.

  11. Use the asynchronous API with asyncio

    master

    For non-blocking calls, use the sp_api.asyncio.api package. You can use the async with context manager pattern to manage the client lifecycle, or call methods directly on the class instances.

    Recommended pattern:

    async with Orders() as orders_client:
        res = await orders_client.get_orders(...)
    import asyncio
    from datetime import datetime, timedelta, timezone
    from sp_api.asyncio.api import Orders, Reports
    from sp_api.base.reportTypes import ReportType
    
    async def main():
        # Using context manager
        async with Orders() as orders_client:
            res = await orders_client.get_orders(
                LastUpdatedAfter=(datetime.now(timezone.utc) - timedelta(days=1)).isoformat()
            )
            print(res.payload)
    
        # Using direct call
        await Reports().create_report(
            reportType=ReportType.GET_MERCHANT_LISTINGS_ALL_DATA
        )
    
    if __name__ == "__main__":
        asyncio.run(main())