If you are interested in our most up to date API check out the full Nexar API here
The latest version of the Nexar Legacy API (formerly Octopart APIv4) is organized around GraphQL, with a newly added REST interface. While you can use the REST wrapper on Nexar Legacy API, we only recommend it as a temporary solution as you transition from Legacy APIv3 to Nexar Legacy API and get set up with our GraphQL interface. We will not continue enhancing and updating APIv3. If you need guidance on transitioning from APIv3 to the Nexar Legacy API REST wrapper, you can find documentation here. If you are ready to move to GraphQL, please continue reading this Getting Started guide.
As of March 31, 2022 we will be discontinuing support for APIv3. As of June 30, 2022 we will be disabling APIv3 altogether. The Getting started guide and reference pages that follow are for the latest release, the Nexar Legacy API.
Please don't hesitate to contact support@nexar.com with any questions.
As of late 2020 PartKeepr is compatible with Nexar Legacy API. We recommend signing up for a Pro tier token to get the most out of the Nexar Legacy API. You can sign up for your Nexar Legacy API token here.
Monthly limits are based on returned part objects. This differs slightly from v3 behavior, which was based on number of http requests.
By default, searches return 10 parts per request, so this means that each request will increment your monthly API usage by up to 10 parts. multi_match requests return 3 parts per query by default, so if you batch request 3 MPN searches using multi_match, by default this will return up to 9 parts.
query MyFirstQuery { categories { name } }
In GraphQL each field must be explicitly requested to be returned. There are three ways to explore the available fields:
ctrl space
to see typeahead suggestions available in the current context.Inspecting the Category schema we see:
type Category { id: ID! parent_id: ID! name: String! ancestors: [Category!]! children: [Category!]! path: String! relevant_attributes: [Attribute!]! }
Let's update our first query to pull back some additional fields:
query MyFirstQuery { categories { path name ancestors { path name } children { path name } relevant_attributes { shortname name } } }
One of the features of graphql is the ability to retrieve properties from related objects. Here we can see that ancestors
and children
are lists of categories, and we can query all the Category fields on these related objects. The same is true of relevant_attributes
which is a list of Attribute
.
As explained in the GraphQL spec the fields in the result will match the ordering of fields requested, and only the requested fields will be returned. This can help make learning and exploring the API easy and fun!
Let's get some parts by ID. The ID can be found at the end of a part URL. So for the page /msp430f5310iptr-texas+instruments-19495124 the ID is: 19495124.
To enable smooth transition, API v3 UIDs are also support, so for /api/v3/parts/7ad5b3df5fb7a512
, you can use the ID 7ad5b3df5fb7a512
query SomeParts { parts(ids: ["1", "2", "asdf", "3", "7ad5b3df5fb7a512"]) { id v3uid manufacturer { name } mpn } }
Some interesting things to point out here:
manufacturer
field is actually a linked company record with it's own set of requested fields. You must specify the desired fields on the related object, and failing to do so will produce an error: Field "manufacturer" of type "Company!" must have a selection of subfields. Did you mean "manufacturer { ... }"?
. The ability to retrieve fields from related objects is why the term Graph appears in GraphQL. Try using the schema tab to explore the Company object and add a field to the manufacturer
field set.1
, the returned ID is actually 46668526
. When duplicate parts are merged, the redirect is followed and the new correct part is returned in place of the merged part.asdf
a null
is returned in the 3rd position. When requesting parts by ID the results will match the order requested, and any misses will be null
.7ad5b3df5fb7a512
is requested using a UID from Octopart's APIv3. In the response we can see both the id
(4
) and the v3uid
(7ad5b3df5fb7a512
). The parts
endpoint allows both numerical part IDs and v3uid values.The search
query is designed to power our search page: It accepts a query (q
) and supports doing aggregations, filtering and sorting results, pagination, etc. Let's look at an example:
query MyPartSearch { search(q: "msp430") { total manufacturer_agg { company { id name } count } results { part { id manufacturer { name } mpn } } } }
From this query we get 3789
hits and the manufacturer_agg
provides aggregations or facets on the result set.
Based on the manufacturer_agg
let's add a filter to only show parts manufactured by Olimex
. Update the search args to read:
search(q: "msp430", filters: {manufacturer_id: "3330"})
After executing we should see a new total of 30 hits, which matches the aggregation. Let's add Texas Instruments
back in:
search(q: "msp430", filters: {manufacturer_id: ["3330", "370"]})
We now see 3690 hits which is the sum of the two buckets in the aggregation.
So far we have been hard coding arguments like ids
and q
. But in a real application you will want to parameterize these arguments. Let's look at an example of doing this:
query MyPartSearch($q: String!, $filters: Map) { search(q: $q, filters: $filters) { total } }
Here we define our custom query MyPartSearch
with two variable arguments: $q
and $filters
. The !
at the end of String!
marks that variable as required.
If we execute now, we'll get an error:
{ "error": { "errors": [ { "message": "must be defined", "path": ["variable", "q"] } ], "data": null } }
In the playground open up the Query Variables tab in lower left hand corner and populate these:
{ "q": "msp430" }
We'll now see our 3789 hits.
To recreate last example:
{ "q": "msp430", "filters": { "manufacturer_id": ["370", "3330"] } }
We'll now see the 3690 we saw earlier.
Search is designed to operate on a single query string and support complex operations like aggregation, sorting, filtering and pagination. Often, though, there is a list of Manufacturer + MPNs and a desire to match many line items at a time. This is common in the BOM use case, and for this we use the multi_match
query.
{ multi_match( queries: [ { manufacturer: "Texas Instruments", mpn: "LM317T" }, { mpn: "SN74S74N", reference: "test", limit: 5 } ] ) { hits reference parts { id slug mpn manufacturer { name } } error } }
This is a copy-pastable Python 2.7+ example client. As you can see it is just a starting point. You are encouraged to customize the query in get_parts
and write new functions to match the operations you need for your application. If you prefer you could define a MyOctopartClient
class to hold the client
instance for you, add metrics, error handling, etc.
from six.moves import urllib
import json
import os
# copy pasted from: https://github.com/prisma-labs/python-graphql-client/blob/master/graphqlclient/client.py
class GraphQLClient:
def __init__(self, endpoint):
self.endpoint = endpoint
self.token = None
self.headername = None
def execute(self, query, variables=None):
return self._send(query, variables)
def inject_token(self, token, headername='token'):
self.token = token
self.headername = headername
def _send(self, query, variables):
data = {'query': query,
'variables': variables}
headers = {'Accept': 'application/json',
'Content-Type': 'application/json'}
if self.token is not None:
headers[self.headername] = '{}'.format(self.token)
req = urllib.request.Request(self.endpoint, json.dumps(data).encode('utf-8'), headers)
try:
response = urllib.request.urlopen(req)
return response.read().decode('utf-8')
except urllib.error.HTTPError as e:
print((e.read()))
print('')
raise e
def get_parts(client, ids):
query = '''
query get_parts($ids: [String!]!) {
parts(ids: $ids) {
id
manufacturer {
name
}
mpn
category {
name
}
}
}
'''
ids = [str(id) for id in ids]
resp = client.execute(query, {'ids': ids})
return json.loads(resp)['data']['parts']
def match_mpns(client, mpns):
dsl = '''
query match_mpns($queries: [PartMatchQuery!]!) {
multi_match(queries: $queries) {
hits
reference
parts {
manufacturer {
name
}
mpn
}
}
}
'''
queries = []
for mpn in mpns:
queries.append({
'mpn_or_sku': mpn,
'start': 0,
'limit': 5,
'reference': mpn,
})
resp = client.execute(dsl, {'queries': queries})
return json.loads(resp)['data']['multi_match']
def demo_part_get(client):
print('\n---------------- demo_part_get')
ids = ["1", "2", "asdf", "4"]
parts = get_parts(client, ids)
for id, part in zip(ids, parts):
print(id, '\t', part)
def demo_match_mpns(client):
print('\n---------------- demo_match_mpns')
mpns = [
'CC4V-T1A 32.768KHZ +-20PPM 9PF',
'LMC6482IMX/NOPB',
'PCF8583T/F5,112',
'FH12-5S-1SH(55)',
]
matches = match_mpns(client, mpns)
for match in matches:
for part in match['parts']:
print(match['reference'], '\t', part['manufacturer']['name'], '\t', part['mpn'])
if __name__ == '__main__':
client = GraphQLClient('https://octopart.com/api/v4/endpoint')
client.inject_token(os.getenv('OCTOPART_TOKEN'))
demo_part_get(client)
demo_match_mpns(client)
curl -H "Content-Type: application/json" -X POST \ -d '{"operationName":null,"variables":{},"query":"{ categories { name }}"}' \ https://octopart.com/api/v4/endpoint?token=MY_TOKEN
At the moment, the GraphQL Playground is not working on Internet Explorer browsers. We're working to get this resource up and running for all browsers. In the meantime, we recommend using an alternate browser of your choice while using the GraphQL Playground.