instructions for beginners

I wrote this text for people who, like me, only heard about Python 3 months ago. For those who know English well, but sometimes want a simple Russian “let’s do it.” For those who decided to write their first request for the Amazon API and do not understand why nothing is working.

Writing a script for Amazon SP-API is like trying to assemble furniture from IKEA without instructions: at first you are glad that you bought a new product, and then you suffer, trying to understand how it even works. More precisely, in this case there are instructions, but according to Amazon support itself, they “do not fully reflect the capabilities of the service.”

In this article I will tell you how to perform the simplest request to receive a token, generate any available report (depending on your “status”), download and read it correctly.

A small digression. Perhaps the names of some variables, functions or anything else will seem strange to you. Please be understanding – I can write in C#, but I have little experience with Python and it’s at the level of “watched two four-hour videos on Youtube.” I'm sure it's possible to optimize something, use libraries, and so on. But we are considering the first steps, which personally were extremely difficult for me to take, because Amazon support has no desire to help, as well as clear instructions in Russian (and often in English too). Everyone is discussing individual errors, not the operation of scripts as a whole.

Preparation

You should start, of course, with instructions and registration. Everything is described in detail in link. There is no point in analyzing something separately here; this does not apply to our script. What you should pay attention to: even if you were given access to your personal gmail, mail, etc. You must register an account using your work email, otherwise you will not be approved by Amazon. Yes, it is possible to create applications if you are a third-party developer, but there are some problems with obtaining keys and access.

The next step is to get Restricted roles to work with orders. This role will allow you to view the buyer's personal information, such as name and address. For this script, we only need the reporting role (for vendors this is Brand Analytics). But I note that ChatGPT does a good job of answering the role questionnaire 🙂

After gaining access, the picture looks like this:

API integration

API integration

Great, click the “Add new app client” button, fill in the name and type of API, indicate all the roles available to us:

Possible roles depend on your request

Possible roles depend on your request

We will need several values ​​from the resulting record, namely Client identifier and Client secret (they are available if you click LWA credentials – View), as well as Refresh Token (you need to click the down arrow next to the Edit App button and select the Authorize option).

Where to click

Where to click

Data for the script to work

Data for the script to run

Step 1. Receive a token from Amazon

About a year ago, Amazon made some changes to its API. There's no need to set up AWS or gain additional access—everything is available right from your Sellers or Vendors Central account. It's just great. The URL for obtaining a token is the same for all marketplaces – https://api.amazon.com/auth/o2/token. First, let's import everything we need:

import requests
import json
import time
import gzip
import pandas as pd

Next, we write the first function to request the key:

def get_access_token():
    url="https://api.amazon.com/auth/o2/token"
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
    }
    data = {
        "grant_type": "refresh_token",
            "refresh_token": "Atzr***", #Ваши данные из настроек
            "client_id": "amzn1.***", #Ваши данные из настроек
            "client_secret": "amz1.***" #Ваши данные из настроек
    }
    response = requests.post(url, headers=headers, data=data)
   
    if response.status_code == 200:
        return response.json()['access_token']
    else:
        raise Exception(f'Refresh token FAIL: {response.text}')

Below we simply run this function:

access_token = get_access_token()

You can also do print to check how it works. At this stage, in case of failure, you will correctly receive error messages, the system will respond quite adequately if you have forgotten a key.

Step 2. Function to request a report

There are several different ways you can sell on Amazon. I work for a vendor company, this is the B2B segment. Our reports are very limited relative to standard sellers, but something can still be done. List of all reports here. I will use GET_VENDOR_INVENTORY_REPORT. You can read more about him here.

Let's get started. First, we need the URL to which we want to send the request. There are several of them; for the Euro-region we use sellingpartnerapi-eu.amazon.com. The list is available at link.

Take the URL, add to it the part about reports and the ID of your marketplace, don’t forget to pass the received token from the first step to the function. Marketplaces can be viewed either in the settings or by link.

def get_vendor_inventory_report(access_token):
    url = f'https://sellingpartnerapi-eu.amazon.com/reports/2021-06-30/reports'
    headers = {
        'Content-Type': 'application/json',
        'x-amz-access-token' : access_token
    }
    body = json.dumps({
        'reportType': 'GET_VENDOR_INVENTORY_REPORT',
        'marketplaceIds': ['A1PA6795UKMFR9'], #Здесь ваш Макретплейс ID
        "reportOptions":{"reportPeriod": "DAY",
                         "distributorView": "MANUFACTURING", 
                         "sellingProgram": "RETAIL"}, 
        'dataStartTime': '2024-10-21',  
        'dataEndTime': '2024-10-21',  
    })
   
    response = requests.post(url, headers=headers, data=body)
   
    if response.status_code == 202:
        print("Starting report preparations!")
        reportId = response.json()['reportId']
        return reportId
    else:
        print("Report FAIL", response.text)
        return None

Adding the launch:

access_token = get_access_token()
reportId = get_vendor_inventory_report(access_token)

Pay attention to the dataStartTime and dataEndTime dates. Amazon has requirements for dates, for example, you cannot specify Sunday as the start date, or you can request a report only for yesterday. Read the description of the report carefully.

Secondly, here we only request a report from the system. We will receive the report itself later.

Great, now we have a reportID that we will use in the next step.

Step 3. Wait for the report

After requesting the report from the previous step, you must wait until it is ready. To do this, we write a new function:

def get_response_information(access_token, reportId):
    url = f'https://sellingpartnerapi-eu.amazon.com/reports/2021-06-30/reports/' + reportId
    headers = {
        'Content-Type': 'application/json',
        'x-amz-access-token' : access_token,
        'x-amzn-RequestId' : reportId
    }
   
    response = requests.get(url, headers=headers)

    while response.json()['processingStatus'] not in ['DONE', 'FATAL']:
        print('Report in queue, stay tuned...')
        print(response.json()['processingStatus'])
        time.sleep(5)
        response = requests.get(url, headers=headers)

    status = response.json()['processingStatus']
    print("Report status: ", status)
    reportDocumentID = response.json()['reportDocumentId']
   
    return reportDocumentID

In this feature, we simply wait for Amazon to respond to us. Several statuses may appear, the main ones being DONE and FATAL. The first indicates that our request is ready and can be downloaded, the second indicates that something went wrong. And here lies one of the problems that I could not solve. The fact is that the answer is contained in the gzip archive. In the next steps we will look at how to read it, but keep in mind that the response may be in the format “The dates are incorrectly specified” or “The request is invalid.” They will not write you a specific error in the request, only general information. Welcome to github or reddit, it's full of discussions about reporting errors. But let's not talk about sad things, the main thing is that at the end we received the ID of the finished document. We complete the execution and move on to the next step.

access_token = get_access_token()
reportId = get_vendor_inventory_report(access_token)
time.sleep(5)
reportDocumentID = get_response_information(access_token, reportId)

Note that I added a sleep timer for five seconds here, because you may encounter a limitation in the number of requests sent to the API. For us it is at the level of two requests per second, but I read that the best practices are to rest per second after the previous request. In this case I made five.

Step 4. Get a link to the report

We send the request again. This time we change the link, the documents are in a different place – reports/2021-06-30/documents:

def get_report_document(access_token, reportDocumentID):
    url = f'https://sellingpartnerapi-eu.amazon.com/reports/2021-06-30/documents/' + reportDocumentID
    headers = {
        'Content-Type': 'application/json',
        'Accept-Encoding': 'application/json',
        'x-amz-access-token' : access_token,
        'reportDocumentId' : reportDocumentID
    }
   
    response = requests.get(url, headers=headers)
    documentUrl = response.json()['url']

    return documentUrldef get_report_document(access_token, reportDocumentID):
    url = f'https://sellingpartnerapi-eu.amazon.com/reports/2021-06-30/documents/' + reportDocumentID
    headers = {
        'Content-Type': 'application/json',
        'Accept-Encoding': 'application/json',
        'x-amz-access-token' : access_token,
        'reportDocumentId' : reportDocumentID
    }
   
    response = requests.get(url, headers=headers)
    documentUrl = response.json()['url']


    return documentUrl

Regardless of the status of the report, you will be given a link to the document. Here I encountered a new problem. We can output this link to the console, to the sky, or anywhere, but when we open the link, there will only be crooked characters. The guys from Youtube that I watched open in normal form. Perhaps they have extensions for chrome or I just don’t have the experience, but I couldn’t watch it without downloading this archive. Yes, don’t forget to add the launch:

access_token = get_access_token()
reportId = get_vendor_inventory_report(access_token)
time.sleep(5)
reportDocumentID = get_response_information(access_token, reportId)
time.sleep(5)
url = get_report_document(access_token, reportDocumentID)

Step 5. Download the archive with our data.

The processing here is simple. We simply open the link and pack all the information into an archive. We won’t really work with files for now, we’ll just point out the most obvious place:

def get_report_information(url, file):  
    file = "file.gzip"
    try:
        response = requests.get(url)

        if response.status_code == 200:
            with open(file, 'wb') as file:
                file.write(response.content)
                print(f'File ready!')
        else:
            print(f'Download file error: {response.status_code}')
   
    except Exception as e:
        print(f'ERROR: {e}')  

That's it, we're done. Well done everyone. And yes, still finish the launch.

access_token = get_access_token()
reportId = get_vendor_inventory_report(access_token)
time.sleep(5)
reportDocumentID = get_response_information(access_token, reportId)
url = get_report_document(access_token, reportDocumentID)
time.sleep(5)
get_report_information(url)

Having finally received my long-awaited report, I wondered: shouldn’t I write a new script that will tell me when the coffee supplies in our kitchen are running low? After all, if I've already gone through Amazon SP-API hell. Behind this simple script there are several days of study and intensive work with various sources.

FAQ

There is a library, why didn't you use it?

I find it difficult to use ready-made libraries when I don't fully understand how they work. A ready-made SP-API library exists, but it will not greatly simplify the steps described in the article.

Your code is ugly, could you do it differently?

I could and have already done so. But for a person just starting his journey in Python development, this was enough. But I'm not at all offended by code reviews. If something really pisses you off, be sure to write it in the comments.

Why not in English?

My level allows me to discuss work topics and issues with people from Germany, France and Italy. But while preparing this simple script, I was immersed in English for 8 hours a day. At some point I thought it would be great to have such instructions in Russian.

Are the keys publicly available?

For this example and the first request – yes. But in the future they are all transferred to an encrypted file, we are considering a simple request to start with.

What's next?

Next we work with files. You can read the report and take from it the necessary data on quantity and price. Then you can update all products with another script and so on. Everything that SP-API can allow is in front of you in the instructions.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *