Asset & Usage Analysis – a Microsoft Power BI Application using the Plantronics ODA API

Download link:
Sample Code for PDC - Power

  • The developer is a certified Power BI engineer and understands how to connect and publish organizational content packs to the Power BI service
  • The developer is a trained administrator for Plantronics Manager Pro and the API ODA suite is active in the Plantronics Manager Pro service
  • The developer has a Power BI Pro subscription and has installed the Power BI Desktop
  • The developer has downloaded the PBIT file from the Plantronics Developer Connection web site
  • The developer has an understanding of both R and M script coding with a 64 bit Windows PC
To begin, open Power BI Desktop by double click on the Power BI template file provided (Asset & Usage Analysis.pbit) which will open in Power BI Desktop. This .pbit file is provided as sample code and does not support refresh in Power BI Service.
  • Enter your Region URL and Tenant API Code and click Load.  The Query Days default is 90 days but may be changed if required.
  • Once the report loads click the Publish button.
  • When prompted, save the file PMP Insights.pbix |
  • A Publish to Power BI pop up will appear as shown below.  Select “My workspace” as the destination and click the Select Button.
  • Click on the Open “PMP Insights.pbix’ in Power BI” hyperlink and enter your Office 365 credentials if requested.
  • The report will open in Power BI Service. As you will see this is a tabbed multi-page report.
  • You can now populate a Dashboard by pinning the report pages or individual visualizations as shown below.
  • The Dashboard is created and named as part of the first pinning as shown below
  • And the Dashboard is created……further tiles of interest can be added from the report in the same way.
Plantronics Developer Connection – Power BI
Implementation of App Authorization Request
In order to connect the Power BI Content Pack to your Plantronics Manager Pro tenant, you require 4 pieces of information, as follows:
  2. API Key
  3. Tenant id
  4. App Id

One of the Partner App Management API methods (requestAppAuthorizationUsingPUT ) sends an App authorization request to Plantronics Manager Pro for the requested tenant - see
This method is used in Power BI to perform the initial app authorization request where you enter your Tenant information when prompted by the Power BI Template file (.pbit).
A description of a Power BI implementation follows 

Power BI Implementation
  1. Going Beyond GET requests

    As a query and reporting tool Power BI lends itself to performing GET requests against REST API. For instance, the following snippet of M Code retrieves Inventory details from the API ODA Sandbox.
    Source = Json.Document(Web.Contents("
    _embedded = Source[_embedded],
    deviceInventoryList = _embedded[deviceInventoryList],
    #"Converted to Table" = Table.FromList(deviceInventoryList, Splitter.SplitByNothing(), null, 
null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table", "Column1", 
{"tenantId", "tenantName", "_links", "product", "lastSeen", "firstSeen", "softphone", 
"device"}, {"Column1.tenantId", "Column1.tenantName", "Column1._links", 
"Column1.product", "Column1.lastSeen", "Column1.firstSeen", "Column1.softphone", 
    #"Expanded Column1.product" = Table.ExpandRecordColumn(#"Expanded Column1", 
"Column1.product", {"productId", "_links", "manufacturer", "family", "name", "modelId", 
"type", "vendorId"}, {"Column1.product.productId", "Column1.product._links", 
"Column1.product.manufacturer", "", "", 
"Column1.product.modelId", "Column1.product.type", "Column1.product.vendorId"})
    #"Expanded Column1.product"
  1. Setup
This is available as a free download from
Please note that this requires a 64 bit Microsoft machine.

Configure the following settings in Power BI Desktop:
  • Privacy Settings - Select Options & Settings / Options and select the Always Ignore Privacy Level settings as shown below.
  • Data Load Settings - Select Options & Settings / Options and select the settings shown below..
  1. Running the Power BI Implementation
  • Double click on the PowerBI template file provided (Authorisation Request.pbit)
  • This will launch in Power BI Desktop
  • Select your Regional Data Access URL from the dropdown list.
  • Enter your PMP Tenant API Code and click the Load button
  • Click Enable script visuals when prompted
  • A "Request Confirmed" message - (200)  will be displayed
  • If the Authorization Request is re-run a "Request Already Submitted" (400) message will be displayed. Note: that these values are displayed per Subscription (e.g. Asset Analysis) and may differ between Subscriptions.
  1. Close Power BI Desktop - Exit & Don’t Save
Sample Code
# Input load. Please do not change #
`dataset` = read.csv(
  check.names = FALSE, encoding = "UTF-8", blank.lines.skip = FALSE);
# Original Script. Please update your script content here and once completed copy below section back #
# to the original editing window #
# check & install required packages using pacman
if (!require("pacman")) {
pacman::p_load("data.table", "httr", "gridExtra")

# get parameters from dataset
sURLDomain <- as.character(subset(dataset$Value, dataset$Key == "URL"))
sTenantAPICode <- as.character(subset(dataset$Value, dataset$Key == "TenantAPICode"))
sAppID <- as.character(subset(dataset$Value, dataset$Key == "AppID"))
sAPIKey <- as.character(subset(dataset$Value, dataset$Key == "APIKey"))

# build list of Subscription IDs
# Ideally, this list should come from another Plantronics API

# initialise list that will contain details of results of authorisation requests
lSubscriptionAuthorisationsRequested <- list()

for (sSubscription in lSubscriptionIDs) {
  # build http PUT request
  sURL <- paste(sURLDomain, "/partner/app/", sAppID, "/authrequests?tenantApiCode=", sTenantAPICode, 
    "&subscription=", sSubscription, sep = "")
  sHeader <- toString(sAPIKey)
  names(sHeader) <- "apikey"
  lResult <- PUT(sURL, add_headers(.headers = sHeader))
  # get result info.
  iStatus <- status_code(lResult)
  lContent <- content(lResult)
  sStatusMessage <- switch (iStatus / 100, "Code 100", "Request successful", "Code 300", lContent$errorMessage, 
  lThisSubscriptionAuthorisation <- list(toString(iStatus), sStatusMessage, sSubscription)
  names(lThisSubscriptionAuthorisation) <- c("Status", "Status message", "Subscription")
  # add to list of results of authorisation requests
  iLengthlSubscriptionAuthorisationsRequested <- length(lSubscriptionAuthorisationsRequested)
  lSubscriptionAuthorisationsRequested[[iLengthlSubscriptionAuthorisationsRequested + 1]] <- lThisSubscriptionAuthorisation

# if any Tenant Subscription authorisations were requested build dataframe for display
if (iLengthlSubscriptionAuthorisationsRequested > 0) {
  lSubscriptionAuthorisationsRequested <- Filter(Negate(is.null), lSubscriptionAuthorisationsRequested) # remove empty rows
  dfSubscriptionAuthorisationsRequested <- data.table::rbindlist(lSubscriptionAuthorisationsRequested)
  gSubscriptions <- tableGrob(dfSubscriptionAuthorisationsRequested, rows = NULL)
  sHeader <- paste("Subscription authorisation request results", "\n\n", "URL: ", sURLDomain, "\n", "AppID:", sAppID, "\n")
  grid.arrange(gSubscriptions, top = sHeader)

Questions? Please use the comment form below.