RESTful QTM API
RESTful QTM API
Table of Contents
Introduction .......................................................................................................................................... 2
General information ............................................................................................................................. 2
Connection ....................................................................................................................................... 2
Endpoints ......................................................................................................................................... 2
URL encoding .................................................................................................................................. 2
Output............................................................................................................................................... 2
Examples .......................................................................................................................................... 3
Endpoints ............................................................................................................................................. 4
API ................................................................................................................................................... 5
Version ............................................................................................................................................. 6
Project .............................................................................................................................................. 7
PAF .................................................................................................................................................. 8
Container format ................................................................................................................................ 14
Container hierarchy ........................................................................................................................ 14
Item structure ................................................................................................................................. 15
Request arguments ......................................................................................................................... 16
Item content.................................................................................................................................... 18
2(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Introduction
This document describes the Representational State Transfer (REST) Application Programming
Interface (API) that can be used to inspect and manipulate data inside of Qualisys Track Manager
(QTM). This interface is hosted by QTM and a server will be started automatically when the
program is started. This document assumes general knowledge of the Hypertext Transfer Protocol
(HTTP), REST and JavaScript Object Notation (JSON). A client can be written in any language that
has support for HTTP.
General information
Connection
Every open instance of QTM hosts a server that can be connected to via HTTP. The port that is used
is currently always port 7979, a port that doesn’t interfere with any standard ports at the time of
writing. This might be made changeable in the future. Currently there is no support for HTTPS.
You can access the QTM API from any computer that has access to the computer running QTM, but
in this text we will assume you’re running QTM on the same computer where you make your
HTTP-requests. The root URL will therefore be http://localhost:7979/ .
Endpoints
All endpoints will begin with a version number. This is part of the versioning scheme that is
elaborated in the sections Endpoints and API. This version number reflects the capabilities of the
interface and the output that will be generated from QTM. In the future when QTM changes the
way the API behaves; the goal of the versioning scheme is that already written clients still will be
functional because they make the requests on whatever version they were written for.
URL encoding
All URL’s are assumed to be URL-encoded (including arguments, excluding message body data),
even if not explicitly stated in this text. For example, raw URL:
http://localhost:7979/root/{BACCC22D9-9FE0-11E4-8F9B-C07D2DFB9814}
Encoded URL:
http://localhost:7979/root/%7BBACCC22D9-9FE0-11E4-8F9B-C07D2DFB9814%7D
In all cases the latter is to be used, even if this document states the former. This is true only for
URL strings (including its arguments). Many clients have support for writing the raw URL without
encoding it first, like most web-browsers for instance, and in those cases you don’t need to worry
about encoding. This is not true for all clients, however, and is dependent on what platform your
client will be written in.
Output
The output format for all commands are always JSON data. The structure of the output, HTTP
request methods, static variables that can be expected and possible response codes are explained for
each individual endpoint in the chapter Endpoints. The main output format for endpoints that
contain data of some kind is explained in the chapter Container format.
3(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Examples
All examples will be made with the program curl (http://curl.haxx.se), which is an open source
command line software for making HTTP requests.
4(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Endpoints
All endpoints in this chapter assumes that the actual URL root is present before the stated root (this
is the host root, not to be confused with container roots). So for instance /api (note the initial root
sign ‘/’) becomes http://localhost:7979/api .The first endpoint of interest when starting to develop
your client is the version number endpoint, which is described in the chapter API. This is where
you’ll find the available versions of the interface. As a rule of thumb you should use the latest
version number available to you when writing your client. All separate versions will have some
breaking changes that won’t work for earlier versions. The versioning scheme allows you to
continue with your version, even though there might exist newer ones.
When referring to a particular endpoint in these sub-sections there will be one of two possible path
types. Either the path is a relative path or an absolute path. An absolute path will have the ‘/’-sign
as a prefix, which indicates that this path is the beginning of the URL, excluding the host address
and port. If the path is a relative path there will be no initial ‘/’-sign and the path is assumed to be
relative to some version. For instance the relative path “project” will become /api/<v>/project,
where <v> denotes whatever version you are using.
In the next sub-sections there will be clauses of endpoints. Each clause might have several
endpoints that are related to the other endpoints in that same clause.
5(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
API
Example:
Note that each value maps to a path relative to the requested URL.
6(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Version
Example:
Project
Example:
PAF
Note: the POST and PUT requests are only available for PAF customers. When doing a GET
request on the root instance, when no PAF-project is loaded, will result in a listing of the files in the
data folder; since the underlying data structure is taken from the data folder hierarchy in the QTM
project.
The instance endpoint has an output that is represented in the general in the separate chapter
Container format. The data that is represented by this endpoint is the data that is available through
PAF. The data (or fields) that are available in this data-tree is dependent on the current project’s
PAF-structure (the “Settings.paf”-file that is located in the root of the project folder). Each child
container represents a file or folder (and other information associated to that node) in the “Project
data tree”, that is available in QTM. To create a new such folder the client makes a POST-request
on a specific node, with the correct “class” and “type” arguments. The arguments correspond to the
class and type in the PAF-structure, as explained in the PAF-documentation. The PUT-request is for
updating data fields in existing containers, and the GET-request outputs the existing values for all
fields available.
The command “start_processing” does not change any fields of the underlying instance. If
successful, QTM will have started the processing step specified in the body of the message.
Processing steps specific to the PAF-project can be listed by querying the instance for items (see the
chapter Item structure for specifics on the output format). The body of the message should contain
the key “Process”; a string identical to a value in the “Processes”-list, supplied by the GET-query
on that instance. A successful command means that the message was correctly formatted and that
the processing step has been initiated. An initiated process does not necessarily mean the process
finished without failure. Possible failures include, but are not limited to; pre-requisites not met, such
as programs not being installed or identified by QTM; failure by the executed process, for example:
9(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Visual 3D fails for any reason. Any such failure can be identified by manual inspection of the QTM
program-state and/or the process being run.
The command “import_file” will import a file into the given instance. The body of the message
should contain the key “FileName”; a string containing the path to the file that should be imported.
The key “Type”; a string containing the name of the measurement type. A successful command
means that the message was correctly formatted and that the file has been imported. Possible
failures include, but are not limited to; Type not being available at the give instance level. Specified
file could not be copied due to access rights.
Example:
In this example we will make a couple of commands and give a brief description of how we know
what data to expect and how to both query PAF-nodes or instances for information as well as
updating information.
We start by opening QTM with a PAF-project. The PAF-project has a “Settings.paf”-file which is
located in the root project folder. Below you’ll find a snippet of the relevant parts that will be used
in this example (your file might differ).
Settings.paf:
Project ID: PAF Gait
Root type: Subject
Default fields: [Creation date, Creation time]
…
Types:
Subject:
Patient:
Fields: [First name, Last name, Date of birth]
Children: [Session]
Directory pattern: $Last name$ $First name$
Icon: paf_patient.ico
Session:
Fields: [Body mass, Height, LegLength, KneeWidth, AnkleWidth, Session
date]
CGA - Clinical Gait Analysis:
Directory pattern: $Session date$-CGA
Measurements: [Static, Gait]
SGA - Simplified Gait Analysis:
Directory pattern: $Session date$-SGA
Measurements: [Static, Gait]
…
Fields:
First name:
Type: String
Inherit: Connect
Last name:
Type: String
10(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Inherit: Connect
Date of birth:
Type: Date
Session date:
Type: Date
When starting QTM, in this example, the “Project data tree” is empty, as shown in Figure 1.
Figure 1
The objective for this example is to add a patient and a session for that patient. Since this PAF-
structure states that the root type of the project is a Subject, we only have one option here and that is
to make a Patient. In this example, these are the allowed “class” and “type” arguments (note that
they are case-sensitive):
Let’s first just see how the data looks when there should be no data:
No children in the root, as expected. Now we will insert a patient: Foo Bar:
Figure 2
We have now successfully created a patient (as shown in Figure 2) and we know its identifier. That
means that if we want to create a session for that patient we do another POST-request on the sub-
URL identified by the identifier:
Notice that we in our previous request didn’t post any data to the container to be generated. That is
perfectly valid, however it might not be very useful. The fields that defines this type will have been
automatically generated and filled with default values, or inherited values. Let’s update two of the
session’s values:
Figure 3
In Figure 3 the final result is illustrated. The extra view on the right is the “Edit field”-dialog that is
available through the right-click menu for files and folders to the left. Note that the value field
“AnkleWidth” is 10m (10000mm). That is because the values are always stored in SI-units. The
final request we will do for this example is to get all of the data that now exists in QTM for this
tree. This will also illustrate how the depth parameter can be used to traverse all the containers:
"ID": "{65E87BB9-D2CC-11E4-AAB8-95106AA09DD6}",
"Name": "20101020-SGA",
"ParentIDs": [
"{7D09E828-D239-11E4-AAB8-95106AA09DD6”,
],
}
],
"Fields": {
"Class": "Subject",
"Filename": "Bar Foo",
"First name": "Foo",
"Last name": "Bar",
"Type": "Patient"
(...)
},
"ID": "{7D09E828-D239-11E4-AAB8-95106AA09DD6}",
"Name": "Bar Foo",
"ParentIDs": [],
}
]
}
Note that some values have been updated automatically by QTM. The field “Filename” has been
updated as well as the file name stored on disk. Some output variables have been removed for
readability.
14(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Container format
The container format is a general data format that is used throughout the API. The reason for this is
that it mimics the internal data structure of QTM and can therefore be translated easily for all data
structures. Changes in the design of the API for this format will also take effect for all data
structures. The API versioning scheme allows for these changes to take place in newer versions,
without affecting clients written for previous behavior.
Container hierarchy
All containers can be viewed as tree data structures, with each node (container) containing some
items (or fields, as they are called in PAF). Any node in the tree can be accessed by referring to the
root node and optionally a unique identifier which points to a specific sub-node in that tree. If no
identifier is specified, the root node is assumed to be the target node. There is no need to refer to a
leaf node by each of its parent nodes; each node’s identifier can be considered unique and is the
only identifier needed, apart from the root, to point to that specific node. The scheme for making
requests is illustrated in the example below.
Figure 4
In Figure 4 the tree root is the container with identifier root. Let us, for the sake of this example,
assume the root resides at the URL: http://localhost:7979/root . By making a GET request at this
URL the items of root will be output. To get the items of the container with identifier eve we would
make a request at http://localhost:7979/root/eve . Similarly, if we would send some argument to
root we would do this like so: http://localhost:7979/root?depth=2 . If you want to pass arguments
for requests to eve the URL would become: http://localhost:7979/root/eve?typeInfo=true . One
thing to keep in mind is that the identifiers for actual container hierarchies will not be names, like in
this example, but rather some number or other form of identifier. No particular format should be
assumed for identifiers, because they will differ between separate hierarchies.
15(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Item structure
Every container has a set of items. An item comes in the form of a key-value pair as the output from
a GET request to any container node. Some items are data that can be modified (for hierarchies that
enables making changes) and some are immutable items that can be expected in every container.
The items that may be modifiable are all grouped in one JSON object called Fields and whenever
you update data (via a PUT or POST request) the items in your JSON body are assumed to be
within the Fields object.
When a GET request is made on the root item in the PAF structure the Children item will always be
present; disregarding the depth parameter. The technical effect of this is that the depth parameter is
increased by one. The reason for this is that the root container contains no extra items (i.e. Fields
object is not present for the root container), except its children. The root, like any other container,
can be queried with extra type info (typeInfo argument set to true), however, and that will generate
the ChildTypes item as expected from any container.
The example output below illustrates a container output from the PAF endpoint (formatted for your
convenience):
{
"ChildIDs": [],
"Fields": {
"Class": "Subject",
"Comments": "",
"Creation date": "2015-05-21",
"Creation time": "08:33:36.276",
"Date of birth": "2015-05-21",
16(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
Note in this example that no depth has been used. This means that there will be no item consisting
of children, except the ubiquitous item ChildIDs. And there is also no parents to this items so the
ParentIDs item is empty.
Request arguments
For POST and PUT requests the arguments will differ from case to case. The current version only
has one container hierarchy that enables POST and PUT requests; namely the PAF structure. The
GET request however has a standardized format. There are two arguments that can be passed to any
such request: depth and typeInfo. A positive depth indicates how many levels of children will be
output and a negative depth indicates how many levels of parents will be output. The default value
is 1, which indicates that only the specified container will be output. From the example in Figure 4,
if the depth parameter would be 2 the output containers would be: root, loner and father. If the depth
was 3 all containers would be output. If the depth was -1 at a child level the child’s parent would be
output in the Parent item and the ParentIDs item would contain the parent id.
The typeInfo parameter is a Boolean and has two possible values: true or false. The default value is
false, which indicates no information will be output for the items. If typeInfo is true, all items will
have been stripped of the value and adds information about the type. Below you’ll find an example
of how items can be output with typeInfo set to true as well as a table of information that might be
available for any particular item.
When doing a POST or PUT request it is assumed that the body is the Fields object, since that is the
only changeable sub-item (everything else is immutable). See the section PAF for an elaborate
example on how to do both a POST and PUT requests.
In the example below a request has been done with the parameter typeInfo set to true.
{
"ChildIDs": [],
17(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
"ChildTypes": [
{
"Class": "Session",
"Type": "CGA - Clinical Gait Analysis"
},
{
"Class": "Session",
"Type": "OTH - Other"
},
{
"Class": "Session",
"Type": "POS - Posture"
},
{
"Class": "Session",
"Type": "SGA - Simplified Gait Analysis"
},
{
"Class": "Session",
"Type": "VID - Video"
}
],
"Fields": {
"Class": {
"Name": "Class",
"ReadOnly": true,
"TypeName": "UnicodeString"
},
"Comments": {
"Name": "Comments",
"ReadOnly": false,
"TypeName": "UnicodeString"
},
"Creation date": {
"Name": "Creation date",
"ReadOnly": true,
"TypeName": "Date"
},
"Creation time": {
"Name": "Creation time",
"ReadOnly": true,
"TypeName": "TimeOfDay"
},
"Date of birth": {
"Name": "Date of birth",
"ReadOnly": false,
"TypeName": "Date"
},
"Directory pattern": {
"Name": "Directory pattern",
"ReadOnly": true,
"TypeName": "UnicodeString"
},
18(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07
"Filename": {
"Name": "Filename",
"ReadOnly": true,
"TypeName": "UnicodeString"
},
"First name": {
"Name": "First name",
"ReadOnly": false,
"TypeName": "UnicodeString"
},
"Last name": {
"Name": "Last name",
"ReadOnly": false,
"TypeName": "UnicodeString"
},
"Path": {
"Name": "Path",
"ReadOnly": true,
"TypeName": "UnicodeString"
},
"Type": {
"Name": "Type",
"ReadOnly": true,
"TypeName": "UnicodeString"
}
},
"ID": "{4E9E8953-FF83-11E4-8BEA-8BD38125EF75}",
"Name": "Bar Foo",
"ParentIDs": []
}
Item content
Items corresponds to internal data in QTM that is stored in a specific way for each item. There is
neither any way to add items nor the ability to change the underlying data-types. Values that have
units are always stored (and should always be updated) according to the SI-unit counterpart; clients
need to perform the conversion themselves.
Table 9 list of available types and the input format used to update values of that type
Type name: JSON format: Additional information:
Int8 Number (i.e. “item”:10) Integer number in the range:
-128 – 127.
Int16 Number Integer number in the range:
(-215) – (215 - 1).
Int32 Number Integer number in the range:
(-231) – (231 - 1).
Int64 Number Integer number in the range:
(-263) – (263 - 1).
Uint8 Number Integer number in the range:
0 – 255.
Uint16 Number Integer number in the range:
0 – (216 - 1).
19(19)
Title Revision Date
RESTful QTM API 1.4 2018-11-07