Skip to main content

Working With APIs

Getting Started

The purpose of this guides is two fold:

  • First, to provide an introduction to those unfamiliar with using the FileWave API
  • Second, to be a reference for commands that can be used within the API

You should know that when we refer to the RESTful API v1 werefers are specifically talking aboutto the original Command Line API.  Recognisable both by the port used and URL paths commencing:  

    /inv/ endpoint. There is a note later in this article that explains how this was brought into the

    FileWave Anywhere API v2 and,refers with a small URL change, you can use commands listed here on TCP 443 with allto the otherweb admin, FileWave Anywhere, API commands.and Therecognisable reasonby youpaths seecommencing:

    20445
    in the URLs of this article is that the RESTful/api/ API v1 uses that port.

    Purpose of an API

    TheAs RESTfuldescribed, API is code built into FileWave server (starting with version 6.x) providing the capability of two-way communication between the FileWave Postgres database and other external systems.  Using the calls in the RESTful API, a FileWave administrator can generate queries, exchange information, and more efficiently integrate inventory data. The RESTful API is designed so that queries and tools created using the current version API will continue to function as future versions of the FileWave server and admin appsAPIs are introduced.

    Many institutions using FileWave for inventory management of their various computing devices also have existing databases for tracking systems. These DB’s could range from simple, in-house SQL databases designed to keepcommunicate trackwith ofsystems.  institutionalAs assetssuch, toFileWave amay full-blown,be commercialleveraged by other systems, e.g. SCCM data engineengines, suchin-house asdatabases, SCCM.etc.  TheTo RESTfulmaintain APIsecurity, containsthere themust mechanisms to integrate those databases into FileWave throughbe an authentication system, followed by a standardized set of queries using the JSON (JavaScript Object Notation - https://json.org) format.

    Possible uses could be integrating existing SCCM data into FileWave queries; sending Fileset information from FileWave backmethod to your help desk database,allow such as Invgate; or integrating purchase order system data into the application license data stored in FileWave.

    The RESTful API provides you, the FileWave administrator, with the abilitycommunication to expandtake the depth of information about your managed systems. Imagine being able to integrate years of detailed inventory stored in your site’s commercial database with the ease of the FileWave Admin’s Inventory queries, or being able to create a simple front end application that alerts you to sudden changes in the software licenses you have enabled across your entire company or campus.place.  The RESTful API provides this kind of expansion of your ability to provide in-depth asset and license managementintegration on an as-needed basis.

    Basic, non-specific command line examples:

    macOS shell

    curl -s -H "Authorization: $auth" \
        https://$server_dns:20443/inv/api/v1/query_result/ \
        --data $query \
        -H "Content-Type: application/json"

    Windows PowerShell

    $header = @{Authorization=“$auth"}
    
    Invoke-RestMethod -Method POST \ 
        -Headers $header \
        -ContentType application/json \
        -Uri https://$server_dns:20443/inv/api/v1/query_result/ \
        -Body $query

    The macOS 'Authorization' or Window's 'Headers' make use of base64 tokens.  From the above code, $auth would need to be set as one of these tokens.

    Each user generated will have their own unique base64 token automatically generated.  This token can be revoked and new tokens created.  Each user may have multiple tokens.

    The Token is the Key

    ForTokens securitymay reasons,be weviewed from FileWave Central App:

      Assistants > Manage Administrators

      Select a desired Administrator and choose the 'Application Tokens' tab.  The token value to copy is the 'Token (base64)'

      image.png

      Token value from above image:

      ezQ1OTQ1ZTI4LWI1OTUtNDFiNS1iZGQwLTYzZDAxM2ExMDkxZn0=

      When choosing accounts and tokens for API interaction, consider making dedicated users for the task(s) required.  Set the permissions of that user to limit their ability to the required task alone.  If the token is compromised, this will needlimit not only the scope of how that token could be used by an attacker, but when revoking and generating a tokennew totoken, accessminimal theimpact RESTful API.  Before version 12.9 there was only one token for inventory (Admin Preferences → Inventory → "Shared Key") that had total read and write access to all data.  Starting in 12.9 there canwould be many application tokens, each with their own rights. 

      experienced.

      For more information on the Application Tokens see the page: Managing FileWave Administrators (Application Tokens)

      We

      will

      API needRequests

      the

      Requests base64could versionbe ofone the token for the rest of the activity.of:

        base64-admin.pngCommand Type Description FigureGET 1.1Returns -a Manageresource Administratorsvalue PUT Replaces a resource PATCH Updates a resource POST Creates a resource DELETE Removes a resource

      SelectData everything (including the = at the end)

      Application Token

      e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=

      An important note on URLs

      FileWave has been around for some time, and there is a slight difference in the URL structure between the old and new versions of the API. To access the new API endpoints, simply add "/api/" to the beginning of the URL. For example, if the old version of the API URL was "/inv/api/", the new URL would be "/api/inv/api/". This change was made during the transition to the API-first approach and the FileWave Anywhere admin console,sent with the new API endpoints now utilizing TCP 443 for communication. If you encounter any issues, ensure that the URL starts with "/api/" to determine if yourequests are using the modern API or the v1 API. Over time, it is advisable to migrate from TCP 20445 to TCP 443 to align with the new API structure.

      This on TCP 443 like all the other API. Notice that it begins with /api/inv/api/

      curl -s -k -H "Authorization: e2M2sssYjIwLTxxx1hMzdiLTFmyyyGIwYTdjOH0=" https://myserver.filewave.net/api/inv/api/v1/query/ \ 
          --header "Content-Type: application/json" -X POST -d @ios16_incompatible.json

      This only with TCP 20445. Notice that it begins /inv/api/

      curl -s -k -H "Authorization: e2M2sssYjIwLTxxx1hMzdiLTFmyyyGIwYTdjOH0=" https://myserver.filewave.net:20445/inv/api/v1/query/ \ 
          --header "Content-Type: application/json" -X POST -d @ios16_incompatible.json

      Breaking down the JSON/Results

      When you send (AKA POST) or receive (AKA GET) inventory information it will be sent/received in the form of JSON.a JSON, as are the responses from those requests.

      JSON data is broken into keyskeys/value andpairs, values.where Onevalues keycould benefiteven of JSON over CSV is the ability to dobe lists inside of lists.

      Examples

      Below examples are using a python tool to reformat the returned response.  Python must be installed to benefit from this. If not, remove the piped section of the command or instal Python.

      For example, doingactioning a GET to look at a list of all theFileWave inventoryServer queriesInventory inQueries, yourcould server,return anda thenJSON similar to the results of one of those queries would look like this:below:

      GET

      List allExisting queriesInventory
      Queries

      1) Get all Queries

      curl -s  -k -H "Authorization: e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=" \
          https://myserver.company.org:20445/inv/api/v1/query/ | python -mjson.tool
      [
          {
              "id": 1,
              "name": "All Windows",
              "favorite": true,
              "group": 1,
              "version": 1
          },
          {
              "id": 2,
              "name": "Mac OS X 10.7-10.11",
              "favorite": false,
              "group": 1,
              "version": 5
          },
      ...
          {
              "id": 103,
              "name": "All Computers to retire",
              "favorite": false,
              "group": 3,
              "version": 2
          }
      ]
      Key Value Description
      id integer The unique number for the query. To be used as reference
      name string The name given to the query
      favorite true/false TheWhether stateor ifnot the query has a check next to it or not toshould show in the sidebar of admin
      group integer The group number given. built-in queries – for example – would be in the "Sample Queries" group, which is group 1. If the user made new groups
      version integer The version for the query. How many times has the query been altered and saved, starting with 1

      GET

      Return the Querydefinition Information
      of a chosen query

      The query information,definition, not the results of the query.  Using ID 1 as an example:

      2) Get Query

      curl -s -k -H "Authorization: e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=" \
          https://myserver.company.org:20445/inv/api/v1/query/1 | python -mjson.tool
      {
          "criteria": {
              "expressions": [
                  {
                      "column": "type",
                      "component": "OperatingSystem",
                      "operator": "=",
                      "qualifier": "WIN"
                  }
              ],
              "logic": "all"
          },
          "favorite": true,
          "fields": [
              {
                  "column": "device_name",
                  "component": "Client"
              },
              {
                  "column": "filewave_client_name",
                  "component": "Client"
              },
              {
                  "column": "name",
                  "component": "OperatingSystem"
              },
              {
                  "column": "version",
                  "component": "OperatingSystem"
              },
              {
                  "column": "build",
                  "component": "OperatingSystem"
              },
              {
                  "column": "edition",
                  "component": "OperatingSystem"
              }
          ],
          "main_component": "Client",
          "name": "All Windows",
          "id": 1,
          "version": 1,
          "group": 1
      }

      Key Value Description
      criteria array Expressions and logic of query

      Criteria Expressions (Each entry will require all of the below.  Add multiple entries to the array as required):
      Key Value Description
      column

      Multiple values

      e.g. 'version', 'device_id', etc.

      Chosen search component 

      (Figure 1.2 #1)

      component

      Multiple values

      e.g. 'Client', 'OperatingSystem', etc.

      Group containing above component

       (Figure 1.2 #2)

      operator

      Multiple values

      e.g.'is', 'begins', etc.

      Method of comparison

      (Figure 1.2 #3)

      qualifier

      Multiple values

      (Either a: String, Integer, Date or Boolean value)

      Value for comparison

      (Figure 1.2 #4)

      Logic:

      Key Value Description

      logic

      Multiple values

      'all', 'none' or 'one'

      How Components should be logically considered for correct return of results

      (Figure 1.2 #5)

      favourite true/false



      Show/Hide from FileWave Central sidebar Inventory Queries
      fields array



      Which components will be shown (ordered first to last)

      Fields to display (Each entry will require all of the below.  Add multiple entries to the array as required):
      Key Value Description

      column

      Multiple values

      e.g. 'device_name', 'name', etc.

      Component to display

      (Figure 1.2 #1)

      component

      Multiple values

      e.g. 'Client', 'OperatingSystem', etc.

      Group containing above component

       (Figure 1.2 #2)

      main_component Selection Box



      Important this is set correctly (Figure 1.2 #6)
      name string



      Inventory Query name shown in FileWave Central
      id integer



      Inventory Query unique number, not already in use. 

      (Each query has a unique number, starting at 1 and incremented with each new query generated when actioned through FileWave)

      version

      integer



      Increment by 1 for each alteration

      group

      integer



      The Inventory Query group which the query should be displayed within.

      E.g. 'group' value of 1 would be within the 'Sample Queries' group

       
      Criteria-admin.png
      Figure 1.2 - Query Builder Criteria

      GETReturn the Inventory Query Results

      3) Get Query Results

      curl -s -k -H "Authorization: e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=" https://myserver.company.org:20445/inv/api/v1/query_result/1 | python -mjson.tool
      {
          "total_results": 13,
          "filter_results": 13,
          "offset": 0,
          "values": [
              [
                  "FW-BLUE-02",
                  "FW-Blue-02",
                  "Windows 10.0",
                  "10.0.0",
                  "10240",
                  "Microsoft Windows 10 Home"
              ],
              [
                  "LAPTOP-C6LLFGH6",
                  "FH-History3",
                  "Windows 10.0",
                  "10.0.0",
                  "14393",
                  "Microsoft Windows 10 Home"
              ],
      ...
          ],
          "version": 3
      }
      Key Value Description
      total_results integer Total count of results
      filter_results integer  
      offset integer  
      values array The results. Repeated for each result. Items depends on what your specified in the fields
      version integer The version for the query. How many times has the query been altered and saved, starting with 1

      Useful Tools

      Converting to/from base64

      Website to encode and decode base64 

        https://www.base64encode.org/ - Encode https://www.base64decode.org/ - Decode

        Using Python

        Python

        #!/usr/bin/env python
        import base64
        import sys
        print "Authorization:", base64.encodestring(sys.argv[1])

        Save as base64encode.py

        Use by:

        ./base64encode.py {780756eb-4cbd-455f-aaa7-d49db12de9d0}

        JSON

        Verify JSON Formatting:

        API Application 

        Browser Extensions

        Commands

        Remember:  All URLs start with

        https://myserver.company.org:20445/inv/api/v1/

        Must include the authorization header

        Below are the optionspossible for use with it.options:

        URLs

        URL Use Options
        Inventory
        query Show all queries GET POST
        query/# Show information on a single query

        Where # is the query ID
        GET PUT DELETE
        query_group/ Show all query group GET POST
        query_group/# Detail information on a single group

        Where # is the group ID
        GET PUT DELETE
        query_result/# Show the results of one query

        Where # is the query ID
        GET POST
        query_count   POST
        component Show all component options on your instance GET
        field_type Show all fields on your instance GET
        License
        license_definition Show all query GET
        license_definition/# Show information on a single license

        Where # is the license ID
        GET
        Custom Fields
        custom_field/ Show all custom fields  
        custom_field/get_association   POST
        custom_field/set_association   POST
        custom_field/upload   POST
        custom_field/usages/<Field_Name> Where <Field_Name> is the Internal Name (E.G "battery_cycle_count") GET
        custom_field/values/   POST
        custom_field/edit/   POST

        Examples

        Using a browser extension

        Using Mod-Header (see tools section), you can make Chrome a RESTful API browser by taking advantage of the FileWave Django Framework. Allowing you to look at theLeveraging URLs and howauthorisation things show up by telling the browsertoken to sendreturn aQuery token as an "Authorization" header each place you go to.Results.

        mod-header.png

        Even if youthe go to a url thatURL is typically a POST url,POST, it provides aan boxoutput belowsimilar youto canthe post withfollowing

        mod-header-post.png

        Using the curl command

        Viewing all available queries (GET)

        curl -s -k -H "Authorization: e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=" https://myserver.company.org:20445/inv/api/v1/query/ | python -mjson.tool

        Posting a new query (POST)

        curl -s -k -H "Authorization: e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=" --header "Content-Type: application/json" -X POST -d @<path/name of new query.json> https://myserver.company.org:20445/inv/api/v1/query/

        Removing a query (DELETE)

        curl -s -k -H "Authorization: e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=" -X DELETE https://myserver.company.org:20445/inv/api/v1/query/<id#>

        For more curl help, see: Using the RESTful API to limit, sort, and offset values returned

        Self-Signed Certificates

        Hopefully everyone is using official certificates. However, if the FileWave Server does have a self-signed certificate, the above commands should fail.  To ignore the warnings the following is required.

        macOS

        Add the -k option to the command.  E.g.

        curl -s -k -H "Authorization: e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=" https://myserver.company.org:20445/inv/api/v1/query/ | python -mjson.tool
        Windows

        PowerShell requires somewhat more code to ignore the warning.  Add the below to the beginning of any script calling an API to a server with a self-signed certificate:

        # Required for self-signed certs only
        function Ignore-SSLCertificates
        {
            $Provider = New-Object Microsoft.CSharp.CSharpCodeProvider
            $Compiler = $Provider.CreateCompiler()
            $Params = New-Object System.CodeDom.Compiler.CompilerParameters
            $Params.GenerateExecutable = $false
            $Params.GenerateInMemory = $true
            $Params.IncludeDebugInformation = $false
            $Params.ReferencedAssemblies.Add("System.DLL") > $null
            $TASource=@'
                namespace Local.ToolkitExtensions.Net.CertificatePolicy
                {
                    public class TrustAll : System.Net.ICertificatePolicy
                    {
                        public bool CheckValidationResult(System.Net.ServicePoint sp,System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Net.WebRequest req, int problem)
                        {
                            return true;
                        }
                    }
                }
        '@ 
            $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
            $TAAssembly=$TAResults.CompiledAssembly
            ## We create an instance of TrustAll and attach it to the ServicePointManager
            $TrustAll = $TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
            $AllProtocols = [System.Net.SecurityProtocolType]'Ssl3,Tls,Tls11,Tls12'
            [System.Net.ServicePointManager]::SecurityProtocol = $AllProtocols
            [System.Net.ServicePointManager]::CertificatePolicy = $TrustAll
        }
        

        Ignore-SSLCertificates
        

         

        Using PHP

        Saved as a php file (like inv.php), update the urlURL and auth code, then place the file on a web server where PHP has been enabled. This creates a webpage that is a 'view onlyonly' web page version of yourthe inventory. People can go toenter the URL for the query andquery, hit refresh as many times as they like,like and will always seeingsee the latest information in inventoryinventory.  All without having to hassle IT for the latest data.

        The output of the query results isn't fancy, but this is to illustrate what can be done.achieved.

        PHP Inventory Viewer
        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">
        <html>
        <?php
        $baseurl="myserver.company.org";
        $port="20443";
        $authcode="e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0=";
        
        
        ini_set('display_errors', 'On');
        ### do not edit below ###
        if (!isset($_GET["qid"])){
        	$url = "https://".$baseurl.":".$port."/inv/api/v1/query/";
        } else {
        	$url = "https://".$baseurl.":".$port."/inv/api/v1/query_result/".$_GET["qid"];
        }
        //  Initiate curl
        $ch = curl_init();
        // Set the url
        curl_setopt($ch, CURLOPT_URL,$url);
        // Disable SSL verification
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSLVERSION, 1);
        // Will return the response, if false it print the response
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        //authenticate
        curl_setopt($ch, CURLOPT_HTTPHEADER,array('Authorization:<'.$authcode.'>=')); 
        // Display errors if any
        if (curl_errno($ch)) { 
           print curl_error($ch); 
        } 
        // Execute
        $result=curl_exec($ch);
        if (curl_errno($ch)) { 
           print curl_error($ch); 
        } 
        $output=json_decode($result, true);
        curl_close($ch);
        
        //create function for looping unknown dimensional array
        function printAll($a) {
          if (!is_array($a)) {
            echo $a, ' <br/>';
            return;
          }
        echo "<br/>";
          foreach($a as $v) {
            printAll($v);
          }
        }
        
        // Start html Page 
        echo '<head>'
        .'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />'
        .'<title>'.$baseurl.'Inventory Page</title>'
        .'</head>'
        .'<body>'
        .'<style type="text/css">'
        ."body {font-family:'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif;}"
        .'h1,h2,h3,h4,{font-weight:100;}'
        .'div {padding:10px; color:#fff; background:#333;}'
        .'div.output{border:1px solid rgba(0,0,0,0.1); background: rgba(0,0,0,0.03); color:#555;-webkit-border-radius:3px;border-radius:3px;margin:15px 25px; padding:10px;}'
        .'tr:nth-child(even) {background: rgba(255,255,255,0.85);}'
        .'tr:nth-child(odd) {background: rgba(0,0,0,0.05);}'
        .'a, a:hover {color:#ce1300; text-decoration:none;}'
        .'</style>'
        .'<div><h1><img src="https://www.filewave.com/images/filewave-1024x788.png" height="60" />'.$baseurl.' Inventory</h1></div>'
        .'<br/>';
        
        // Default homepage
        if (!isset($_GET["qid"])){
        	echo "<table>"
        	."<thead>"
        	."<tr>"
        	."<th>&hearts;</th>"
        	."<th>Query Name</th>"
        	."<th>Query ID</th>"
        	."</tr>"
        	."</thead>"
        	."<tbody>";
        	foreach ($output as &$value) {
        		if ($value['favorite'] == true) { $fav="&hearts;";} elseif ($value['favorite'] == false) {$fav=" ";}
        		echo "<tr><td>".$fav."</td><td>".$value['name']."</td><td><a href='".$_SERVER['PHP_SELF']."?qid=".$value['id']."&n=".$value['name']."'>".$value['id']."</a></td></tr>";	
        	}
        	echo"</tbody></table>";
        }
        //If an individual query has been selected
        elseif (isset($_GET["qid"],$_GET["n"]))  {
        	echo "<h3>Home &gt; Query: "
        	.$_GET["n"]
        	."</h3><hr/>"
        	."<strong>Total Results: </strong>"
        	.$output['total_results']
        	."<br/>"
        	.'<strong>First Column results: </strong>';
        
        	foreach ($output['values'] as &$value) {
        		echo $value['0'].' <strong> &nbsp; | &nbsp; </strong>';
        	}
        echo "<br/>"
        ."<strong> All Results: </strong><br/><div class='output'>";
        printAll($output['values']);
        echo "</div>";	
        #var_dump($result);
        }
        else {
        	echo "<h1 style='color:#ff0000;'> An error has occurred</h1> Parhaps you used a bookmark and the URL has changed";
        }
        ?>
        <hr/>
        <center><font style=" font-size:9px;"><a href="http://filewave.com" target="_blank">&copy; BenM@ FileWave</a></font></center>
        </body>
        </html>