Making Api Calls More Efficient

Discussion in 'Shapeways API' started by TheKnottyCelt, Apr 3, 2020.

  1. TheKnottyCelt
    TheKnottyCelt Member
    I working at grabbing a comprehensive list of all my models and their costs (material basePrice), so that I can run it through my product configuration database which will calculate the wholesale and retail prices of the finished products based on the basePrice returned by the API. I have been able to script the appropriate calls to get the required information (see code below), however; it takes a considerable amount of time due to the number of API calls required.

    Code:
    import requests
    class Product:
        def __init__(self, id, name, material, price):
            self.id = id
            self.name = name
            self.material = material
            self.price = price
    
    def getAccessToken(cliendId,clientSecret):
        api_url = 'https://api.shapeways.com/oauth2/token'
        post_data = {
            'grant_type': 'client_credentials'
        }
        response = requests.post(url=api_url, data=post_data, auth=(cliendId,cliendSecret))
        return response.json()['access_token']
    
    def getHeaders(accessToken):
        headers = {
            'Authorization': 'Bearer ' + accessToken
        }
        return headers
    
    def getModelIds(clientId,clientSecret=''):
        if clientSecret == '':
            accessToken = clientId
        else:
            accessToken = getAccessToken(clientId, clientSecret)
        page = 1
        modelIds = []
        while True:
            api_url = 'https://api.shapeways.com/models/v1?page=' + str(page)
            response = requests.get(url=api_url, headers=getHeaders(accessToken))
            if response.json()['models'] == None:
                break
            for model in response.json()['models']:
                modelIds.append(model['modelId'])
            page +=1
        return modelIds
    
    def getProduct(response,modelId,material):
        modelName = response.json()['title']
        if ':' in material['name']:
            mat, ot = material['name'].split(':')
        else:
            mat = material['name']
        return Product(modelId,modelName,mat,material['basePrice'])
    
    def getModelDetail(clientId,clientSecret='',modelIds=[])
        if clientSecret == '':
            accessToken = clientId
        else:
            accessToken = getAccessToken(clientId,clientSecret)
        if modelIds == []:
            modelIds = getModelIds(accessToken)
        modelDetail = []
        for modelId in modelIds:
            api_url = 'https://api.shapeways.com/models/' + modelId + '/v1'
            response = requests.get(url=api_url +'?', headers = getHeaders(accessToken))
            modelName = response.json()['title']
            materials = response.json()['materials']
            for material in materials:
                modelDetail.append(getProduct(response,modelId,materials[material]))
        returl model Detail
    
    As you can see, I have a class called Product which holds the id, name, material and price of a given Product. Calling getModelDetail returns an array of Product items. One Product for each model/material pair in the supplied list of modelIds. Like I mentioned, this works as-is, but takes a considerable amount of time. Is there a more efficient way to achieve the same result? Do I really need a new API request for each page of models? Do I absolutely need a new API request for each and every single model? Is there a method I am missing which would reduce the number of API requests, and thus reduce the run-time of the script?
     
  2. stonysmith
    stonysmith Well-Known Member Moderator
    Does the Pricing CSV not have the information you need in it?
    https://www.shapeways.com/shop/pricing-csv#

    It's not the API.. simple http calls will retrieve it.
    I use it instead of the API for prices - still has to be paged, but takes like 5 minutes to get the whole list.
     
  3. TheKnottyCelt
    TheKnottyCelt Member
    Yes and no. The Pricing CSV will show me the required information for models which are associated with products. Since my models are mostly parts to products which I finish myself before packaging and shipping to my customers, it adds otherwise unnecessary steps to the process. It is something with which I have simply been dealing with up until now. I have been manually downloading the CSV before my database imports the database crunches the numbers, and spits out the queries required to update my eCommerce and POS databases.

    Since my database is already setup to work with the CSV, I suppose a follow up question to my OP would be, “Which http calls would accomplish this?”