Accessing Altium 365 design data

The Nexar API is a GraphQL based API for accessing the Altium ecosystem, including supply chain data from Octopart, design data from Altium 365 and manufacturing services from Altimade.

This guide is a quick guide to accessing design data in the Nexar API. It uses the Banana Cake Pop IDE for most of the examples and shows off some of the query capabilities of the API. It is not exhaustive, nor a complete reference, but designed to get you started, quickly.

This guide assumes you are familiar with Altium 365 and that you are a member of at least one workspace.

Step 1: Nexar Accounts

Nexar.com is the home of Nexar on the web. Today, we have a simple portal that you can go to to get started with the Nexar API.

Navigate to the landing page and click on the “Sign In” link.

This will redirect you to the Nexar identity server to authenticate you:

Sign in with your Altium 365 credentials. These credentials are the same as your Altium Live credentials, which are a common set of credentials used across Altium’s digital properties, Nexar included.

The first time you sign in to Nexar, you will need to create an organization (unless you have already been invited to join one in which case you’ll skip this step). Give your organization a name:

Click create and you’ll be logged into the portal:

Step 2: Nexar Applications

Applications are a fundamental concept in Nexar - you need an application to be able to interact with the API. The application essentially provides an “identity” to the API - whenever an API call is made, it is in the context of an application. Things like query limits, scopes (what API endpoints the application is authorized to call), etc. are part of the application definition and configuration.

Before you query the API, you will need to create an application. Click on the “Click to Create Application” button:

Enter some details for the application, including a name and a description, and only enable the “Design” scope as we will only be querying design data with this application:

You will get a confirmation dialog:

The application will show up in your dashboard. Click the “Manage applications” link or the “Applications” menu item to go to the list of applications:

You can create a maximum of 3 applications at present.

Click on the “Show Details” button on an application to take a peek inside:

The application details page show you various information about the application:

You can:

  • Find the Client ID and Client Secret (needed for OAuth2 flow)

  • Configure redirect URLs (part of Authorization Code OAuth2 flow)

  • Generate time limited OAuth2 access token for API access

  • Run examples and get access to source code on GitHub

Step 3: The Banana Cake Pop IDE

The Nexar API is built on top of an open source GraphQL server called Hot Chocolate. There is a built-in IDE called Banana Cake Pop, or BCP for short. This is a really powerful web based IDE for running queries.

Go to https://api.nexar.com/graphql to access the IDE: To learn how to configure this to use your Nexar application credentials visit the FAQ for using OAuth2 with the Nexar/BCP IDE. If there is no error from the ‘Fetch Token’ action the IDE is ready for the next step.

BCP will authenticate. You may be asked to login as below, but this will likely not happen if you are already logged into nexar.com:

BCP will now be authenticated using your application details, and crucially, the user details that you are logged into nexar.com with. This is important to understand - the application is working on behalf of you, the user, and when you query the design API, you are querying data based on what you have access to!

Authentication tokens used by Nexar will be valid for 24 hours. After that time the queries in the rest of this guide will produce a response similar to this:

When you see this simply go back to the connection settings and click on fetch token to re-authorize BCP.

Step 4: Running Queries

Now that we have BCP authenticated, you are ready to start executing some queries. GraphQL provides an introspection capability that means the IDE has a full understanding of the Nexar API schema, so we get really nice things like intellisense style code suggestions and autocomplete. Use <ctrl>space to trigger a list of code options that fit in the context of the current line position as shown below:

The first query we are going to run is to get a list of our workspaces. Type out the following query to see it in action, or simple copy and paste the below into the document tab:

query GetWorkspaces {
    desWorkspaces {
        name
        description
        url
        location {
            apiServiceUrl
        } 
    }
}

Click the “Execute” link to run the query:

This query has asked for the workspace name, description and URL, and returned it in the response:

That’s it! We’ve completed our first query!

Get Projects in a Workspace

After getting a list of workspaces, we can then create another query to get a list of projects in a specific workspace. Construct a query like that shown below - you’ll need to provide your own URL. We are going to use the result from the previous GetWorkspaces query here.

Before executing the query, we are going to change the GraphQL query endpoint to the optimal query endpoint, the “apiServiceUrl”, returned in the GetWorkspaces query. Click the settings icon and change the Schema Endpoint:

Note that we don’t have to do this - we could continue using the api.nexar.com/graphql endpoint and it will work. The reason we change it is so that we get the best performance, as the workspace data is hosted in the region that we are connecting to, so we don’t end up with unnecessary latencies.

Type the following query and execute it:

query GetProjects {
    desProjects(workspaceUrl: "https://solvethirteen.365.altium.com/") {
        nodes {
            id
            name
            description
        }
    }
}

You’ll get results like the following:

Note in this query we have the fields we want to query wrapped in this strange “nodes” element. This is because this query uses cursor based paging. For queries that will potentially return large amounts of data, we use paging to make things efficient such that we return smaller chunks of data, and only the data we are interested in.

Let's take a close look at what we can do. Change the query to be the same as below:

query GetProjects {
    desProjects(workspaceUrl: "https://solvethirteen.365.altium.com/") {
        totalCount
        pageInfo {
            hasNextPage
            hasPreviousPage
            startCursor
            endCursor
        }
        nodes {
            id
            name
            description
        }
    }
}

Then take a look at the result:

{
  "data": {
    "desProjects": {
      "totalCount": 49,
      "pageInfo": {
        "hasNextPage": true,
        "hasPreviousPage": false,
        "startCursor": "MA==",
        "endCursor": "OQ=="
      },
      "nodes": [
        {

Here, we now have the total number of items which is 49, and we have cursor information telling us the beginning and end of the page.

Let’s adjust the query to get the next page:

query GetProjects {
    desProjects(workspaceUrl: "https://solvethirteen.365.altium.com/", after: "OQ==") {
        totalCount
        pageInfo {
            hasNextPage
            hasPreviousPage
            startCursor
            endCursor
        }
        nodes {
            id
            name
            description
        }
    }
}

Here we have said “Give me the projects after the page “OQ==” and that is exactly what we got back. Note, if you have less than 10 projects in your workspace, everything will fit in one page and the above query will return nothing

Get a Project By Name

We can also build a query to get a specific project by name:

query GetProject {
    desProjects(workspaceUrl: "https://solvethirteen.365.altium.com/",
        where: {name: {eq: "AltimadeTest01"}}) {
        nodes {
            id
            name
            description
        }
    }
}

Here we use the “Where” clause to specify the name of the project. The response will be something like:

{
  "data": {
    "desProjects": {
      "nodes": [
        {
          "id": "RGVzUHJvamVjdApkaHR0cHM6Ly9zb2x2ZXRoaXJ0ZWVuLjM2NS5hbHRpdW0uY29tL3xEOTkwN0QwQy1EQjI3LTRDNDgtODdDMi02MTZDMzgxMTA3OTV8MA==",
          "name": "AltimadeTest01",
          "description": ""
        }
      ]
    }
  }
}

Get Project By Id

In the previous query we got an ID for a project. This next query will drill down into the data model to show just how much information can be obtained from the design. Let’s start with a basic query that queries by ID:

query GetProjectById {
    desProjectById(id: "RGVzUHJvamVjdApkaHR0cHM6Ly9zb2x2ZXRoaXJ0ZWVuLjM2NS5hbHRpdW0uY29tL3xEOTkwN0QwQy1EQjI3LTRDNDgtODdDMi02MTZDMzgxMTA3OTV8MA==") {
        name
        description
    }
}

The result we get will be something like:

{
  "data": {
    "desProjectById": {
      "name": "AltimadeTest01",
      "description": ""
    }
  }
}

Get PCB Nets and Pads

Example query for getting nets and pads:

query GetDesignInfo {
    desProjectById(id: "RGVzUHJvamVjdApkaHR0cHM6Ly9zb2x2ZXRoaXJ0ZWVuLjM2NS5hbHRpdW0uY29tL3xEOTkwN0QwQy1EQjI3LTRDNDgtODdDMi02MTZDMzgxMTA3OTV8MA==") {
        name
        description
        design {
            workInProgress {
                variants {
                    pcb {
                        nets {
                            name
                            cumulativeLength {
                                xMm
                            }
                        }
                        pads {
                            radius
                            holeSize {
                                xMm
                            }
                            position {
                                xMm
                                yMm
                            }
                        }
                    }
                }
            }
        }
    }
}

Get PCB Comments

Example query for getting components on the PCB:

query GetDesignInfo {
    desProjectById(id: "RGVzUHJvamVjdApkaHR0cHM6Ly9zb2x2ZXRoaXJ0ZWVuLjM2NS5hbHRpdW0uY29tL3xEOTkwN0QwQy1EQjI3LTRDNDgtODdDMi02MTZDMzgxMTA3OTV8MA==") {
        name
        description
        design {
            workInProgress {
                variants {
                    pcb {
                        commentThreads {
                            comments {
                                text
                            }
                        }
                    }
                }
            }
        }
    }
}

Get BOM

Example query for getting BOM information:

query GetDesignInfo {
    desProjectById(id: "RGVzUHJvamVjdApkaHR0cHM6Ly9zb2x2ZXRoaXJ0ZWVuLjM2NS5hbHRpdW0uY29tL3xEOTkwN0QwQy1EQjI3LTRDNDgtODdDMi02MTZDMzgxMTA3OTV8MA==") {
        name
        description
        design {
            workInProgress {
                variants {
                    bom {
                        bomItems {
                            bomItemInstances {
                                isFitted
                                designator
                            }
                            component {
                                name
                                details {
                                    symbols {
                                        imageThumbnailUrl
                                    }
                                    footprints {
                                        imageThumbnailUrl
                                    }
                                }
                                manufacturerParts {
                                    companyName
                                    partNumber
                                    supplierParts {
                                        companyName
                                        partNumber
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Get Component Library

The component library is paged. Here is any example query:

query GetLibrary {
    desLibrary(workspaceUrl: "https://solvethirteen.365.altium.com/") {
        components {
            nodes {
                name
                comment
                description
                manufacturerParts {
                    companyName
                    partNumber
                    priority
                }
                details {
                    parameters {
                        name
                        value
                        type
                    }
                    symbols {
                        imageThumbnailUrl
                    }
                    footprints {
                        imageThumbnailUrl
                    }
                }
            }
        }
    }
}

And a fragment from the response:

         {
            "name": "CMP-00114-1",
            "comment": "0603YD334KAT2A",
            "description": "CAP,.33UF,16V,X5R,10%,SMD, 0603,TR<AZ",
            "manufacturerParts": [
              {
                "companyName": "Kyocera AVX",
                "partNumber": "0603YD334KAT2A",
                "priority": 0
              }
            ],
            "details": {
              "parameters": [
                {
                  "name": "Case Code (Metric)",
                  "value": "1608",
                  "type": "TEXT"
                },
                {
                  "name": "Mount",
                  "value": "Surface Mount,PCB",
                  "type": "TEXT"
                },
                {
                  "name": "Tolerance",
                  "value": "10%",
                  "type": "TEXT"
                }
              ],
              "symbols": [
                {
                  "imageThumbnailUrl": "https://ccv-eu.s3.eu-central-1.amazonaws.com/…"
                }
              ],
              "footprints": [
                {
                  "imageThumbnailUrl": "https://ccv-eu.s3.eu-central-1.amazonaws.com/…"
                },
                {
                  "imageThumbnailUrl": "https://ccv-eu.s3.eu-central-1.amazonaws.com/…"
                },
                {
                  "imageThumbnailUrl": "https://ccv-eu.s3.eu-central-1.amazonaws.com/…"
                }
              ]
            }
          },

Summary and Resources

As you can see, the Nexar API is really flexible and powerful, allowing you to build your own queries and get access to the things that you are interested in.

Here are some further resources:

Couldn't find an answer to your question?

Get in touch at support@nexar.com