Skip to main content

RESTful API (v1 API) Copy

GettingCommand StartedLine RESTful API

TheIt purposeis ofprobably easiest to consider this guidesAPI isas twoan fold:interaction with Inventory Queries, allowing for example:

  • First,Ad-hoc to provide an introduction to those unfamiliar with using the FileWave API
  • Second,queries to be arun referenceto forreturn commandsresults
  • that
  • New canInventory Queries to be usedcreated
  • within
  • The thereturning APIof Current Query results
  • Deleting queries

You should know that when we refer to the RESTful API v1 we are specifically talking about the /inv/ endpoint. ThereThey is a note later in this article that explains how this was brought into the FileWave Anywhere API v2 and, with a small URL change, you can use commands listed here on TCP 443 with all the other API commands. The reason you see 20445 in the URLs of this article is that the RESTful API v1 uses that port.

Purpose of an API

The RESTful 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 apps 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 keep track of institutional assets to a full-blown, commercial data engine such as SCCM. The RESTful API contains the mechanisms to integrate those databases into FileWave through 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 back to your help desk database, 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, witheven the ability to expandread or alter Custom Field values for devices.

Examples:

Returning an Inventory Query request

FileWave GUI example

Imagine it is desirable to return a list of macOS devices which have a network interface name that contains 'en', the depthField to be returned is the Device Name and the Main Component is 'MacOS Device'.  The criteria would appear as below:

image.png

JSON Data Example

A RESTful API query, to return the same set of informationresults, aboutwould yourhave manageda systems.JSON Imaginestructure beingset ableout toas:

integrate
{
    years“criteria”: of{
        detailed“column":"interface_name",
        inventory“component":"NetworkInterface",
        stored“operator”:”contains",
        in“qualifier":"en"
    your},
    site’s“fields":[
        commercial{
            database“column”:"device_name",
            with“component":"Client"
        }
    ],
    “main_component":"MacOSClient"
}

It can be seen that the easeJSON ofblock is just mimicking the FileWave Admin’sCentral Inventory queries,Query.  or

being

Creating ablean toInventory createQuery

a simple front end application that alerts you to sudden changes in

On the softwareKB licensespage youexplaining havewhat enabled across your entire company or campus. The RESTfulan API provides this kind of expansion of your ability to provide in-depth asset and license management on an as-needed basis.

The Token isis, the Key

following

Forexamples securitywere reasons, we will need a token to access the 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 can be many application tokens, each with their own rights. shown:

ForCommand moreLine information on the Application Tokens see the page: Managing FileWave Administrators (Application Tokens)

We will need the base64 version of the token for the rest of the activity.

 
base64-admin.png
Figure 1.1 - Manage Administrators

Select 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, 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 you 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/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

ThisFileWave onlyAnywhere with TCP 20445. Notice that it begins /inv/api/
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

BreakingThese downdemonstrate a method of creating a new Inventory Query by providing the JSON/Results

JSON

Whenas youa sendfile, (AKArather POST)than or receive (AKA GET) inventory information it will be sent/receivedtext in the formactual script line, using the POST option.

Interacting with Custom Fields

The first thing to appreciate, is all Inventory items have an 'Internal Name'.  This is unique to each item and of JSON.course Custom Fields also therefore have their own Internal Name.

JSONInternal isNames brokenmay intobe keys and values. One key benefit of JSON over CSV is the ability to do lists inside of lists.

For example, doing a GET to look at a list of all the inventory queriesviewed in yourFileWave server,Central and then the results of one of those queries would look like this:

GET all queries 

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
    }
]
thewindowwillreportthe
KeyValueDescription
idintegerThe unique number for the query. To be used as reference
namestringThe name given to the query
favoritetrue/falseThe state if the query has a check next to it or not to showwhen in the Inventory Query viewer.  Select any item in the left hand sidebar and the bottom of admin
group integer TheInternal groupName.

number

image.png

given.
Reading built-inValues
queries

Perhaps – for example –it would be indesirable to read the "SampleCustom Queries"Field group, which is group 1. If the user made new groups

versionintegerThe version for the query. How many times has the query been altered and saved, starting with 1

GET the Query Information

The query information, not the resultsvalue of the query.above 'macOS Instal Flag' Custom Field for a device, for example, based upon its serial number.  The JSON data block might look something like:

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"serial_number",
      "component": "OperatingSystem"Client",
      "operator": "="is",
      "qualifier": '\"WIN"
            }
        ],
        $serial_number\"logic": "all"'
    },
    "favorite": true,
  "fields":
    [
       {
        "column": "device_name"macos_instal_flag",
        "component": "Client"
        },
        {
            "column": "filewave_client_name",
            "component": "Client"
        },
        {
            "column": "name",
            "component": "OperatingSystem"
        },
        {
            "column": "version",
            "component": "OperatingSystem"
        },
        {
            "column": "build",
            "component": "OperatingSystem"
        },
        {
            "column": "edition",
            "component": "OperatingSystem"CustomFields"
      }
    ],
  "main_component": "Client",
    "name": "All Windows",
    "id": 1,
    "version": 1,
    "group": 1
}

Using this method, it is possible to provide the Serial Number as a variable value; as such the same script could be ran on all devices, without the need to edit the script.  Note the internal name used for the Custom Field as well as the single quotes around the $serial_number variable.

Editing
Values

As

analterationofacurrentvalue,thewhentheupdateoccurred
Key Value Description
criteria array Expressionscommand would then use the PATCH option.  In this instance, the Custom Field to alter has an 'internal name' of 'admin_test', is a Boolean entry and logicthe JSON data block could look like:

{
  "CustomFields":
    {
      "admin_test":
      {  
          "exitCode":null,
          "status":0,
          "updateTime":"'$current_time'",
          "value":true
      }
    }
}

When Custom Fields are updated, a time stamp of query


Criteriais Expressionsshown.  (EachWhen entryaltering willthe requirevalue allfrom the Command Line API, the time should be supplied, along with the value and a couple of other key/value pairs.  There should be no reason to provide an other value than those shown for 'exitCode' and 'status', when adjusting using the API.

Date is important and should be of the below.format Add"2018-09-10T15:48:08Z":

multiple

macOS entriesexample:

to
current_time=$(date -u +"%FT%TZ")

The code would look something like the arrayfollowing, where $query would be set as required):the

KeyValueDescription
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:

KeyValueDescription

logic

Multiple values

'all', 'none' or 'one'

How Components should be logically considered for correct return of results

(Figure 1.2 #5)

favouritetrue/false



Show/Hide from FileWave Central sidebar Inventory Queries
fieldsarray



Which components will be shown (ordered first to last)

Fields to display (Each entry will require allcontent of the below.  Add multiple entries to the array as required):
KeyValueDescription

column

Multiple valuesJSON:

e.g.macOS '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_componentSelection Box



Important this is set correctly (Figure 1.2 #6)
namestring



Inventory Query name shown in FileWave Central
idinteger



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

GET the Query Results

Get Query Resultsshell

curl -s -k -H "Authorization: e2FjYzRkYmQzLTI3ZjYtNDEyMi1iMGVhLTI1YmY0OGNmYWM0NX0="$auth" \
    https://myserver.company.org:20445/$server_dns:20443/inv/api/v1/query_result/1 | python\
    -mjson.tool
X
{PATCH "total_results":\
    13,-data "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
}
KeyValueDescription
total_resultsintegerTotal count of results
filter_resultsinteger 
offsetinteger 
valuesarrayThe results. Repeated for each result. Items depends on what your specified in the fields
versionintegerThe 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 

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 options for use with it.

URLs

URLUseOptions
Inventory
queryShow all queriesGET POST
query/#Show information on a single query

Where # is the query ID
GET PUT DELETE
query_group/Show all query groupGET 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
componentShow all component options on your instanceGET
field_typeShow all fields on your instanceGET
License
license_definitionShow all queryGET
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 the URLs and how things show up by telling the browser to send a token as an "Authorization" header each place you go to.

mod-header.png

Even if you go to a url that is typically a POST url, it provides a box below you can post with

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"

Windows PowerShell

$header = @{Authorization=“$auth"}

Invoke-RestMethod -XMethod POSTPATCH \ 
    -dHeaders @<path/name$header of\
    new-ContentType query.application/json> \
    -Uri https://myserver.company.org:20445/$server_dns:20443/inv/api/v1/query/query_result/ \
    -Body $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

Using PHP

Saved as a php file (like inv.php), update the url and auth code, then place the file on a web server where PHP has been enabled. This creates a webpage that is a view only version of your inventory. People can go to the URL for the query and hit refresh as many times as they like, always seeing the latest information in inventory 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.

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>