Skip to main content

Inventory Reporting & Management

Background

The Inventory Reporting API is useful to create detailed inventory reports of sites, rooms, and devices.

Some examples include device aggregations, device queries, device count, and site & room information.

Remember that the GraphQL Explorer is tied to your user's authentication when testing the sample queries below. If your user can access multiple tenants, the query response is aggregate data from those tenants.

If you need to test within a specific tenant, we've exposed an option to use Client Credentials - also known as an API Connection. To select a set of credentials, click the Client Credentials toggle in the upper left-hand corner of the page, select the credentials you want to use from the dropdown list, and then continue on with your testing.

Deprecated Queries

Poly Lens APIs have evolved over recent months as we've worked to optimize the device querying experience. There are two queries which are now deprecated, devices and searchDevices. While both of these queries still "work", they're not as optimized to handle querying large batches of device data. The new deviceSearch query offers a better way to handle pagination and supports returning results of more than 10k entries.

If you've begun development using either of the prior queries, it would be worth the effort to update your queries to use deviceSearch moving forward. deviceSearch fields use edges and nodes - this is a relational structure that supports pagination and is different than the legacy devices query. deviceSearch also uses the DeviceFindArgs type for argument parameters. You'll see some examples of this structure in our queries below.

Querying Devices

We'll start by running a query to return information pertaining to devices in our tenant. There are many fields available, but in this example we'll focus on returning the following fields: name, hardwareFamily, softwareVersion, activeApplicationName, hasPeripherals, and connections.

By default, the number of devices returned is 10. However, if you need more than 10 devices returned, you can use the pageSize variable to set a different amount. The minimum is 1 and the maximum is 5000. When you set the number of devices returned you can use the pageInfo fields to return totalCount, countOnPage, nextToken, and hasNextPage - all which are helpful when dealing with pagination. To keep the sample response concise, we'll change the number to 2 in our examples.

Query Devices Using deviceSearch

Test this query in the GraphQL Playground

query allDevices($params: DeviceFindArgs) {
deviceSearch(params: $params) {
edges {
node {
name
hardwareFamily
hardwareModel
softwareVersion
activeApplicationName
hasPeripherals
connections {
connected
allPeripheralsLinked
name
}
}
}
pageInfo {
totalCount
countOnPage
nextToken
hasNextPage
}
}
}

Variables

{
"params": {
"pageSize": 2,
"sort": {
"fields": [
{
"direction": "ASC",
"name": "id"
}
]
}
}
}

Sample Response

{
"data": {
"deviceSearch": {
"edges": [
{
"node": {
"name": "Poly Lens Desktop",
"hardwareFamily": "Lens App Family",
"hardwareModel": "Lens Desktop",
"softwareVersion": "1.0.7",
"activeApplicationName": null,
"hasPeripherals": null,
"connections": [
{
"connected": true,
"allPeripheralsLinked": false,
"name": "BT700"
}
]
}
},
{
"node": {
"name": "Savi 8200 Office Series",
"hardwareFamily": "Savi Family",
"hardwareModel": "Savi 8200 Office Series",
"softwareVersion": "3863",
"activeApplicationName": null,
"hasPeripherals": null,
"connections": []
}
}
],
"pageInfo": {
"totalCount": 3485,
"countOnPage": 2,
"nextToken": "MmozNTliZGxslkbnQxODNu",
"hasNextPage": true
}
}
}
}

Querying Specific Device Details

The deviceSearch query is incredibly powerful as it provides insight for all devices in a tenant. You'll likely need to aggregate this data in different ways. To support various levels of granularity, we provide an expansive list of filter options. We'll take a look at a few of these filter options in the next examples.

Let's say we're building a page for Room Video devices and want to know which devices are running in Zoom Mode. We can accomplish this by targeting the activeApplicationName field in the deviceSearch query.

For our query we want to know the: device name, serial number, hardware model, activeApplicationName (Provider Mode), activeApplicationVersion (Provider APK Version), and room name & floor they're assigned to.

We'll do this by passing in two filter variables: contains and field. Effectively we're saying for all devices, look at the activeApplicationName field and if it contains "Zoom" return it to me.

Note: The provider name passed into the contains field is case sensitive.

Query Devices Running Zoom Rooms

Test this query in the GraphQL Playground

query zoomDevices($params: DeviceFindArgs) {
deviceSearch(params: $params) {
edges {
node {
name
serialNumber
hardwareModel
activeApplicationName
activeApplicationVersion
room {
name
floor
}
}
}

pageInfo {
totalCount
countOnPage
nextToken
hasNextPage
}
}
}

Variables

{
"params": {
"pageSize": 2,
"filter": {
"contains": "Zoom",
"field": "activeApplicationName"
},
"sort": {
"fields": [
{
"direction": "ASC",
"name": "id"
}
]
}
}
}

Sample Response

A few things to note in the query response:

  • The activeApplicationVersion field - The ability to see the application version is helpful for folks managing Poly OS devices running Ecosystem Partner APKs.
  • The nodes returned - We're limiting the countOnPage to 2 items (for conciseness). But if you look at the totalCount you'll see we have 65 items running Zoom Rooms mode.
{
"data": {
"deviceSearch": {
"edges": [
{
"node": {
"name": "DFR StudioX70",
"serialNumber": "superSecretSerialNumber",
"hardwareModel": "Studio X70",
"activeApplicationName": "Zoom Rooms",
"activeApplicationVersion": "5.13.5.2468",
"room": {
"name": "Jedi Enclave",
"floor": "2"
}
}
},
{
"node": {
"name": "DFR StudioX30",
"serialNumber": "superSecretSerialNumber",
"hardwareModel": "Studio X30",
"activeApplicationName": "Zoom Rooms",
"activeApplicationVersion": "5.12.0.1972",
"room": {
"name": "Skywalker Ranch",
"floor": "4"
}
}
}
],
"pageInfo": {
"totalCount": 65,
"countOnPage": 2,
"nextToken": "NHU2MTybWpic2Jt",
"hasNextPage": true
}
}
}
}

Query Devices with the OR: Filter

If you have deployed Poly Video devices running either Native Zoom Rooms or Microsoft Teams Rooms, you might want to build a view to display this information. While there are many ways to implement this on the front end, you'll need to build a query to return the devices with this data. You can accomplish this using the OR: filter.

Test this query in the GraphQL Playground

query msftAndZoomDevices($params: DeviceFindArgs) {
deviceSearch(params: $params) {
edges {
node {
name
serialNumber
hardwareModel
activeApplicationName
activeApplicationVersion
room {
name
floor
}
}
}
pageInfo {
countOnPage
totalCount
hasNextPage
nextToken
}
}
}

Variables

{
"params": {
"pageSize": 2,
"filter": {
"OR": [
{
"contains": "Zoom",
"field": "activeApplicationName"
},
{
"contains": "Microsoft",
"field": "activeApplicationName"
}
]
},
"sort": {
"fields": [
{
"direction": "ASC",
"name": "id"
}
]
}
}
}

Sample Response

{
"data": {
"deviceSearch": {
"edges": [
{
"node": {
"name": "DFR StudioX30",
"serialNumber": "superSecretSerialNumber",
"hardwareModel": "Studio X30",
"activeApplicationName": "Microsoft Teams",
"activeApplicationVersion": "1449/1.0.96.2022120503",
"room": {
"name": "Skywalker Ranch",
"floor": "3"
}
}
},
{
"node": {
"name": "DFR StudioX70",
"serialNumber": "superSecretSerialNumber",
"hardwareModel": "Studio X70",
"activeApplicationName": "Zoom Rooms",
"activeApplicationVersion": "5.13.5.2468",
"room": {
"name": "Jedi Enclave",
"floor": "2"
}
}
}
],
"pageInfo": {
"countOnPage": 2,
"totalCount": 33,
"hasNextPage": true,
"nextToken": "cHknJlcjBueTMwZg=="
}
}
}
}

Query Devices with the OR: & AND: Filters

If you wanted to take the example above one step further and build the ability to filter your devices on the Provider Mode (activeApplicationName) and the Hardware Model (hardwareModel) you can use the AND: & OR: filters. In the following example we're saying, if the device is running in Zoom Rooms or Microsoft Teams mode and it's a Studio X50, return it to me.

Test this query in the GraphQL Playground

query zoomMsftDevices($params: DeviceFindArgs) {
deviceSearch(params: $params) {
edges {
node {
name
serialNumber
hardwareModel
activeApplicationName
activeApplicationVersion
room {
name
floor
}
}
}
pageInfo {
countOnPage
totalCount
hasNextPage
nextToken
}
}
}

Variables

{
"params": {
"pageSize": 2,
"filter": {
"AND": [
{
"contains": "Studio X50",
"field": "hardwareModel"
},
{
"OR": [
{
"contains": "Zoom",
"field": "activeApplicationName"
},
{
"contains": "Microsoft",
"field": "activeApplicationName"
}
]
}
]
},
"sort": {
"fields": [
{
"direction": "ASC",
"name": "id"
}
]
}
}
}

Sample Response

{
"data": {
"deviceSearch": {
"edges": [
{
"node": {
"name": "DFR Studio X50",
"serialNumber": "superSecretSerialNumber",
"hardwareModel": "Studio X50",
"activeApplicationName": "Microsoft Teams",
"activeApplicationVersion": "1449/1.0.96.2022120503",
"room": {
"name": "Bantha Plains",
"floor": "2"
}
}
},
{
"node": {
"name": "DFR Studio X50",
"serialNumber": "superSecretSerialNumber",
"hardwareModel": "Studio X50",
"activeApplicationName": "Zoom Rooms",
"activeApplicationVersion": "5.13.6.2489",
"room": {
"name": "Oga's Cantina",
"floor": "3"
}
}
}
],
pageInfo": {
"countOnPage": 2,
"totalCount": 15,
"hasNextPage": true,
"nextToken": "Z2F4eHprc3eG92ZWE0NGt4"
}
}
}
}

Query CCX Hardware Revisions

If you're using Poly Lens to manage your CCX inventory and need to know which CCX 400 & 500 hardware revisions you've deployed, you can use the Lens APIs to aggregate this data.

There are two ways to use the Lens APIs:

  1. Use the GraphQL Playground to run the query and export the results to .csv
    1. This approach is best for those who don't write code/scripts
    2. It involves using Excel to format the .csv results
  2. Grab the example Query and Arguments from the GraphQL Playground and implement into your scripting language of choice
    1. This is more upfront work but removes the need to parse the data through external tools (like Excel)

This article details using the GraphQL Playground to query the data and export the results to .csv

For those using the GraphQL Playground, we'll break the process down into these steps:

  1. Query Structure
    1. Tenants with < 500 CCXs
    2. Tenants with > 500 CCXs
  2. Formatting the .csv Data in Excel
    1. Text to Columns Wizard
    2. Creating Column Headers
    3. Removing Remaining Characters
    4. Format as Table

It's important to note that the GraphQL Playground uses User Authentication. If your user can access multiple Poly Lens tenants, the query response is aggregate data from those tenants. If you're in this position and need to isolate the scope to a single tenant, you can create an API Connection or pass the tenantId into the arguments of the example query we've pre-configured for you.

Query Structure

We'll use the deviceSearch query to return each CCX's name, hardwareModel, macAddress, hardwareRevision, softwareVersion, site, & room. These fields should provide enough information to accomplish the task. However, if you don't have CCXs assigned to a room or site, or don't need/want certain fields we've included, you can remove them from the query and proceed.

In the Variables section, we filter by hardwareModel to return only CCX 400 and 500 models. pageSize is set to return 500 CCXs at a time to avoid rate-limiting. If you need to know how many CCXs you have, you can run the query and look at the totalCount field.

If the totalCount is less 500, refer to Tenants with < 500 CCXs If the totalCount exceeds 500, refer to the Tenants with > 500 CCXs

Access this query in the GraphQL Playground

Poly GraphQL Playground operation and variables image

Tenants with < 500 CCXs

If pageCount returned less than 500 devices, click the table icon in the Response section of the UI. The results will appear in a table view and expose a .csv download button. Download the .csv and proceed to Formatting the .csv Data in Excel

Poly GraphQL Playground response with csv download

Tenants with > 500 CCXs

The pageInfo fields contain the information required to use pagination. Of the four fields, nextToken is the one we need to use. The Variables > params > nextToken field will be null the first time you run the query.

Poly GraphQL Playground variables field with null nextToken field

Now, run the query and look at the Response section. If the totalCount exceeds the pageSize, nextToken will contain an alphanumeric string.

Poly GraphQL Playground query response with nextToken string

Click the table icon and look at the edges row. You'll see an option to download the .csv results.

Poly GraphQL Playground Pass nextToken String into Arguments

Copy the nextToken string from the query response and paste it into the Variables > params > nextToken field before running the query to fetch the next batch of results. Make sure you download the .csv each time you run the query and fetch the next batch of results.

Poly GraphQL Playground Pass nextToken String into Arguments

Continue copying the nextToken, running the query, and downloading the csv until the response returns nextToken: null.

Poly GraphQL Playground Pass nextToken String into Arguments

Formatting the .csv Data in Excel

Each CCX we've queried has the same key and value format. The goal is to create a usable Excel table by filtering/parsing the unnecessary characters, removing the duplicate keys, and creating a column with a single key (as a header) for each CCX corresponding value.

This section covers the more accessible more manual way to format the query results in Excel. If you're an Excel power user, this section won't be helpful for you. Feel free to skip it and perform the Excel formatting magic of your choice.

For the rest of us, we'll start by ensuring we have a single .csv as our primary document. If you have < 500 devices and only one .csv file, congrats, you saved a little work and should proceed to the Text to Columns Wizard

If you have > 500 devices and have downloaded multiple .csv files, open the first one and delete row A1. This file will be our primary working document.

For each additional .csv, the process remains the same. Open the file and cut/paste all rows (except A1) into the primary document. After you've moved all rows to the primary document, the result/structure of the file will look similar to this.

Excel formatting and combining all csv&#39;s into a single file

Text to Columns Wizard

The data for each device is in the first cell of each row, even though it spans across the table. To filter and parse this information, select all in Column A, click the Data tab, and click Text to Columns

Select all data in column A, click data tab, and click text to columns wizard

Text to Columns has limitations, so we can't parse all characters in a single step. However, it gets us most of the way there.

Text to Columns - Step 1 of 3: Choose the Delimited character type and click Next

text to columns step 1 choose delimited character type

Text to Columns - Step 2 of 3: In the Delimiters section, select Comma, Other, and add a colon (:) into the field.

text to columns step 2 select delimeters comma, other, add semicolon for other

Text to Columns - Step 3 of 3: Make sure General is selected in the Column data format field. Click Finish.

text to columns step 3 select general column data format

Creating Column Headers

The next step is to create column headers for the values. First, insert a new row at the top of the table. Then, you can cut/paste the key into the row's corresponding column or type it manually. The .csv splits the site name and room name into separate columns. Combine these values into a single column header. Now, you can select and delete all columns containing the same key.

create column headers and delete columns with repetitive keys

Removing Remaining Characters

The } is the last character we need to remove. Using Find and Replace, add a } in the Find what field and a blank space in the Replace with field. Click Replace All and the result will be a cleanly formatted table.

find curly bracket and replace with a blank space

Format as Table

Select all the data cells and use Format as Table to make the table easier to read and filter. During this step, make sure to select My table has headers.

format at table with headers

prettier table with filtering

And just like that, you've used the GraphQL Playground to query data from your Poly Lens tenant, parsed the results, and created a usable table to drill into the details. Nice work! 👏🏼

Please reach out if you have specific content requests or questions.