How To Use The Octopart API

How To Use The Octopart API

This article will show you how to use the? Octopart API using Python.

Octopart is a product of Nexar Cloud Platform . Nexar is a division of Altium? , and in Feb 2024 Renesas Electronics announced the acquisition of Altium.

Nexar has 8 products, one is Octopart and another is the API access to Octopart data which they call the Nexar API. For simplicity I will continue to refer to it as the Octopart API.

An important thing to understand about API's is that every one is custom.

While there are certain conventions, every API has been set up and configured differently depending on the implementation of the API owner.


API Basics

The most common types of API are REST, SOAP, and GraphQL.

  • REST communicates via HTTP and is the most common and simplest, it typically involves multiple endpoints that pull pre-defined sets of data.
  • SOAP uses XML and is enterprise grade favored for security.
  • GraphQL is query language using a single endpoint and requires the user to exactly specify the data they want.?

Octopart once used REST, but now uses GraphQL.

This makes it easy to request very specific data, like say the lifecycle status for a part. Sometimes this is very helpful. But...

A very important consideration with Octopart is the distinction between a query and matched parts. A single query may have X number of matched parts and may return Y number of data fields.

You pay for the number of matched parts in every query no matter how many data fields you return.

This tends to make it in your interest to request a large amount of data for each matched part and then parse out what you actually want from the returned JSON.

If you make a single query with a wildcard at the end that returns 100 part numbers, that is 100 matched parts even if you only requested lifecycle status for each one.

You can limit the number of matched parts returned, be sure you do!


Getting Started

The Octopart API is divided into two data sets which they call Scope, Design and Supply. You can access these depending on what you sign up and pay for.

Today we will focus on the Supply Scope.

You start here to sign up with Nexar for API access. Initially you have up to 100 matched parts in their Playground for free.

Once signed up there is a free tier that allows up to 1000 matched parts.

After signing up you will log into the Portal, you may need to be patient and reload the page a couple times especially if returning from the day before.

Once in the Portal you will create an app via the Create app button.

Then go your app, then to the Authorization tab, generate an Access Token, then paste your Access Token, Client ID, and Client Secret somewhere secure for use in a moment.


Using the API with Python

Here is code to place near the top of your script that will be used with the specific queries later.

You will need to manage your ID and Secret according to your best practice.

For simplicity you can just replace the variables NEXAR_CLIENT_ID and NEXAR_CLIENT_SECRET with text you saved earlier.

This approach is fine for quick start, but remember to go back and use better secrets management later.

import httpx #pip install if necessary# Global session for API's
client = httpx.Client()

#Initialize GraphQL Query
clientId = NEXAR_CLIENT_ID
clientSecret = NEXAR_CLIENT_SECRET
NEXAR_URL = "https://api.nexar.com/graphql"
PROD_TOKEN_URL = "https://identity.nexar.com/connect/token"


def get_token(client_id, client_secret):
? ? """Return the Nexar token from the client_id and client_secret provided."""

? ? if not client_id or not client_secret:
? ? ? ? raise Exception("client_id and/or client_secret are empty") ? ? ? ?
? ? else:
? ? ? ? token = {}
? ? ? ? try:
? ? ? ? ? ? #token = requests.post(
? ? ? ? ? ? token = client.post(
? ? ? ? ? ? ? ? url=PROD_TOKEN_URL,
? ? ? ? ? ? ? ? data={
? ? ? ? ? ? ? ? ? ? "grant_type": "client_credentials",
? ? ? ? ? ? ? ? ? ? "client_id": client_id,
? ? ? ? ? ? ? ? ? ? "client_secret": client_secret
? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? follow_redirects=False,
? ? ? ? ? ? ).json()?
? ? ? ? except Exception:
? ? ? ? ? ? raise
? ? ? ??
  ? return token


def decodeJWT(token):  ? 
? ? return {
? ? ? ? "exp": time.time() + 3600 ?# Token expires in 1 hour for demonstration
? ? }

class NexarClient:
    token_flag = False

? ? def __init__(self, id, secret) -> None:
? ? ? ? self.id = id
? ? ? ? self.secret = secret
? ? ? ? self.s = httpx.Client()
  ? ? ? self.s.keep_alive = False  ? ? ? 

? ? ? ? # Perform token initialization only once
? ? ? ? if not NexarClient.token_flag:
? ? ? ? ? ? self.token = self.retrieve_or_generate_token()

? ? ? ? ? ? # Update headers with the current token
? ? ? ? ? ? self.s.headers.update({"Authorization": f"Bearer {self.token.get('access_token')}"})
? ? ? ? ? ? self.exp = decodeJWT(self.token.get('access_token')).get('exp')
? ? ? ? ? ? NexarClient.token_flag = True ?# Set flag to True after initialization
? ? ? ? else:
? ? ? ? ? ? print("Token already initialized.")

     def retrieve_or_generate_token(self):
  ? ? ? """Retrieve token or generate a new one if necessary."""
  ? ? ? try:  ? ? ? ? ? 
? ? ? ? ? ? if token_data:
? ? ? ? ? ? ? ? # Check expiration
? ? ? ? ? ? ? ? exp = decodeJWT(token_data['access_token']).get('exp')
? ? ? ? ? ? ? ? if exp < time.time() + 300:
? ? ? ? ? ? ? ? ? ? print("Token expired or about to expire. Generating a new one.")
  ? ? ? ? ? ? ? ? ? token_data = get_token(self.id, self.secret)  ? ? ? ? ? ? ? ? ? 
? ? ? ? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ? #print("Token not expired.")
? ? ? ? ? ? ? ? ? ? pass
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? #print("No token found. Generating a new one.")
  ? ? ? ? ? ? ? token_data = get_token(self.id, self.secret)  ? ? ? ? ? ? ? 

  ? ? ? ? ? return token_data

     def get_query(self, query: str, variables: Dict) -> dict:
          """Return Nexar response for the query."""
 ? ? ? ? ?if NexarClient.token_flag:
               try:               
                    r = self.s.post(
                        NEXAR_URL,
                        json={"query": query, "variables": variables},
                    )             
                    response = r.json()

                   # Handle unauthorized error indicating token issues
  ? ? ? ? ? ?      if r.status_code == 401 or "errors" in response:
  ? ? ? ? ? ?           #print("Token validation failed. Please provide a valid access token.")  ? ? ?  ? ? ??
  ? ? ? ? ? ? ? ? ?     # Regenerate a new token
  ? ? ? ? ? ? ? ? ?     #print("Regenerating a new token...")
  ? ? ? ? ? ? ? ? ?     self.token = self.retrieve_or_generate_token()
  ? ? ? ? ? ? ? ? ?     self.s.headers.update({"Authorization": f"Bearer {self.token.get('access_token')}"})
? ? ? ? ? ? ? ? ? ??
  ? ? ? ? ? ? ? ? ?     # Retry the query with the new token
  ? ? ? ? ? ? ? ? ?     r = self.s.post(
  ? ? ? ? ? ? ? ? ? ? ?      NEXAR_URL,
  ? ? ? ? ? ? ? ? ? ? ?      json={"query": query, "variables": variables},
  ? ? ? ? ? ? ? ? ?         )
  ? ? ? ? ? ? ? ? ?         response = r.json() ? ? ? ? ? ? ? ? ?  
? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ??
  ? ? ? ? ?    except Exception as e:
  ? ? ? ? ? ? ?     #print(e)
  ? ? ? ? ? ? ?     raise Exception("Exception error while getting Nexar response")

  ? ? ? ? ?    if "errors" in response:
  ? ? ? ? ? ?       for error in response["errors"]:
  ? ? ? ? ? ? ? ? ?      #print(error["message"])
  ? ? ? ? ? ? ? ? ?      raise Exception("Errors in response while getting Nexar response")
? ? ? ? ? ? ? ??

  ? ? ? ? ?    return response["data"]

# Reusing a single NexarClient instance
nexar = NexarClient(clientId, clientSecret)        

?Whew. With this code in place you are ready to make a query. Here is a base template you can use.

def SearchMPN(que):        
    gqlQuery = '''
    query SearchMPN ($que: String! {  
      supSearch(
        q: $que        
        start: 0
        limit: 1 
        ){   
            results  {      	
                part  {
                    mpn
                    genericMpn
                    akaMpns
                    manufacturer {name}
                    shortDescription
                    sellers (authorizedOnly: true) {   
                        company {name}
                            offers { 
                            packaging
                            factoryPackQuantity
                            multipackQuantity
                            inventoryLevel
                            moq
                            orderMultiple                                                   
                                prices {                
                                    quantity
                                    price        
                                }                            
                            clickUrl    
                            }			

                    }
                }
            }    
        }
    }
    '''    
    
    # Execute the query with the provided query variable
    data = nexar.get_query(gqlQuery, {"que": que})
return data        

This code creates a Python function named SearchMPN that requires a text input which will be a part number. You might use it something like this:

part = "AD7685ARM"
part_json_data = SearchMPN(part)        

Now the variable part_json_data will contain all the requested fields in JSON format.

Let's breakdown the query itself.

Notice the lines start and limit.

Remember a query may want to return multiple matched parts. These lines tell the API to return matched parts beginning with the first one (0 is the first record number in Python) and to return only 1.

That is how you limit the number of matched parts returned.

The labels SearchMPN are not used by the API and can be whatever you want.

SupSearch is the important part. This is part of the GraphQL query language that was created by the designer of the API.


Introducing the Schema

Meet your new best friend, the Interactive Schema .

It is too large and complex to display here, but the important thing is to start with the table on the left, these are Query Roots.

All queries must begin with one of these Query Roots.

If you look at the Schema you will see a root named supSuggest with a line to the fields available for return.

Notice the variables q, start, and limit, are not specified in the Schema for supSuggest.

The only way I could discover the variables was by trial and error in the Playground, which will autocomplete as you type. The same is true for the authorizedOnly: true filter after sellers.

In the Schema, follow the line to SupPartResultSet. You will never use this name. You may specify any of the fields in SupPartResultSet in your query.

Notice that each field might be a Int!, String!, or another result set. If it is another result set you must specify what you want from that result set, and this can continue many layers deep.

As in the example above, you will very frequently want to query supSuggest>results>parts. Hopefully by comparing the Schema to the code example above you will understand how to get to what you want.

Now that you have your JSON file you can use ChatGPT to guide you with how to parse and use the JSON.

Just provide ChatGPT a sample of the output so it understands the JSON structure, then describe what you want to accomplish.

Once you are able to return this data into your own applications you will have opened up a whole new world of component data connectivity, good luck!

要查看或添加评论,请登录

Everett Frank的更多文章

  • How EMS Can Drive Profit With AI

    How EMS Can Drive Profit With AI

    How can an EMS company increase profits in the next 12 months? New customers? Perhaps, but unlikely. Consider: On…

  • Here's What AI Can Actually Do For Sourcing Today.

    Here's What AI Can Actually Do For Sourcing Today.

    After a year spent deep in the weeds understanding and programming AI for electronic component sourcing, I’ve recently…

    2 条评论
  • If components could talk, what would you ask?

    If components could talk, what would you ask?

    Imagine walking into a room filled with all the electronic components you need to buy this week. Now, imagine if each…

    1 条评论
  • How To Prompt ChatGPT

    How To Prompt ChatGPT

    AI For Procurement Series - Part 2 Learn how to improve your results with ChatGPT using 5 best practices. In this…

    1 条评论
  • How AI Works

    How AI Works

    AI For Procurement Series - Part 1 Learn the basics of ChatGPT, LLM's and Prompt's. We'll accomplish this by explaining…

  • What is CPH?

    What is CPH?

    Component placements per hour (CPH) is fundamental to understanding the capabilities of an SMT line. If you want to…

  • 3 Easy Steps To Reshoring PCBA's

    3 Easy Steps To Reshoring PCBA's

    Here's an instant and easy way to see if your printed circuit board assemblies (PCBA's) can be made in the USA at…

  • What is Should Cost Analysis?

    What is Should Cost Analysis?

    Should cost analysis ("should costing") was developed by the Defense Department to assist procurement officers in…

  • Should I Tell EMS Suppliers What Others Have Quoted?

    Should I Tell EMS Suppliers What Others Have Quoted?

    If they deserve it, yes. If you buy only on the basis of price, then no.

  • Understanding EMS Price Variances

    Understanding EMS Price Variances

    How much should you expect prices to vary between EMS companies? The answer is about 5 percent. EMS companies use a…

社区洞察

其他会员也浏览了