API Overview
The Smári Application Program Interface (API) provides a REST type architecture providing a simple, scalable interface to the core functionality of the Smári platform. It allows:
- Remote access to data in the Smári database for custom analyses.
- Ability to push data remotely into the Smári database
The motivation for creating an API interface to Smári is to handle situations such as:
- I am a clinical user of Smári. I am doing some analysis on my QA data that goes beyond the built-in analyses. I would like to easily import specific data from Smári into my custom analysis application.
- I am a clinical user of Smári in an academic or research setting. I have developed a number of custom image processing routines that are very specific to my needs. I would like to have an API toolkit from IO that would allow me to directly send the data to Smári automatically.
- I am a manufacturer of QA hardware or software. I would like to provide database tools on cloud infrastructure to my customers to send information from my systems to Smári without waiting for a lengthy development cycle. I would like to be able to have my engineers easily put together a software component to accomplish this.
API Workflow
In order to communicate with the API, the following steps must be followed.
- Generate an API key within Smári.
- Use the key to request an access token for the API
- Use the returned access token to use HTTP methods to communicate with the API (GET, POST, PATCH, etc)
Generating an API Key
Y
You must have administrative rights to generate API keys.
- In your Smári account, navigate to the "Manage - Application Programmer Interface" page.
- Click the +Add Token button and enter a descriptive name for your key.
A key will be generated and displayed on the main API page. You may generate multiple keys for your account. Each key must have a unique label.
- Click on the icon to the right of the key to copy to the clipboard.
Modifying API Keys
To modify an existing API key click on the Edit button next to the key and provide a new unique label. If you hover over the Edit button with the cursor, it will say Modify token. Note that the label is used when requesting access tokens to the service so changing the label may break existing code requesting access.
Deleting API Keys
To delete an API key click the Delete button next to the key. Note that any code using the key will not function once it is deleted.
Requesting an Access Token
The base URL for all API calls to Smári is https://smari.phantomlab.com/api/rest. In order to make a call to receive an access token. In order to request access to the API service send a POST request to http://smari.phantomlab.com/api/rest/oauth with the JSON body:
{
"client_id": "The descriptive id you set up above",
"client_secret": "The generated key string",
"grant_type": "client_credentials"
}
Note: the ID will be a concatenation of a number and the label you assigned. Copy the entire label (e.g 180:API_Connection)
MATLAB Example
%% Get the Access Token using the API Key we generated
%this is the basic information needed
r.client_id = 'label you provided';
r.client_secret = 'generated key';
r.grant_type = 'client_credentials';
%...make the request
options = weboptions('MediaType','application/json','RequestMethod','post');
tokenRequestResponse = webwrite('https://tqa.imageowl.com/api/rest/oauth',r,options);
%...display the authorization
disp('The response to the access request');
disp(tokenRequestResponse);
Python Example
This example uses the Python requests package.
import json
import requests
class tqa_Connect:
def demo(self):
payload = {"client_id": "Your API Label",
"client_secret": "Your API Key",
"grant_type": "client_credentials"
}
r = requests.post('https://smari.phantomlab.com/api/rest/oauth',data = payload)
print 'Status Code:',r.status_code
j = r.json()
accessToken = j['access_token']
print 'Access Token: ',j['access_token']
tqa_Connect().demo()
R Example
This example uses the R httr package.
library(httr)
url <- 'https://smari.phantomlab/api/rest/oauth'
body <- list(client_id = 'Your API Label', client_secret= 'Your API Key',grant_type = 'client_credentials')
# get the access token in a respone
r <- POST(url, body = body, encode = "form")
tqa_token <- content(r,"parsed")
# look at access token
str(tqa_token)
C# (.NET) example
We need to establish some basic data contract classes to make the JSON formatting easier.
For some discussion using Data Contracts in .NET see Using Data Contracts and How to use HttpClient to post JSON data
For the request.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
namespace TQA_API_Demo
{
[DataContract]
public class AccessRequest
{
[DataMember(Name = "client_id")]
public String ClientID { get; set; }
[DataMember(Name = "client_secret")]
public String ClientSecret { get; set; }
[DataMember(Name = "grant_type")]
public String GrantType { get; set; }
}
}
And to store the response
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
namespace TQA_API_Demo
{
[DataContract]
public class accessRequestResponseData
{
[DataMember(Name = "access_token")]
public String AccessToken { get; set; }
[DataMember (Name= "expires_in")]
public int ExpiresIn { get; set; }
}
}
And then the call to get the access token.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json; // uses the Json.NET assembly a freely available JSON library
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.IO;
namespace TQA_API_Demo
{
class Program
{
static void Main()
{
RunAsync().Wait();
}
static async Task RunAsync()
{
using (var client = new HttpClient())
{
// TODO - Send HTTP requests
Uri baseAddress = new Uri("https://tqa.imageowl.com/");
client.BaseAddress = baseAddress;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var accessRequestData = new AccessRequest()
{
ClientID = "Your API Label",
ClientSecret = "Your API Key",
GrantType = "client_credentials"
};
//HTTP get the access token
HttpResponseMessage response = await client.PostAsJsonAsync("api/rest/oauth", accessRequestData);
if (response.IsSuccessStatusCode)
{
accessRequestResponseData responseData = await response.Content.ReadAsAsync<accessRequestResponseData>();
Console.WriteLine("{0}\t{1}",responseData.AccessToken,responseData.ExpiresIn);
}
Console.ReadLine();
}
}
}
}
Detailed API call formats
Detailed information on API calls can be found at https://smari.phantomlab.com/api/documentation/TqaAPI-v1. In general, the raw tab contains the most in-depth information and examples of each call.
Calling HTTP Methods on the Smári API
Once you have an access token you can make HTTP requests to the API. API tokens expire in 1 hour from their creation.
Each API request will be made to a different URL in the API.
All API requests will include the same header information:
- Content-Type => application/json,
- Accept => application/json,
- Authorization => Bearer AccessTokenThatYouCopied
POST and PATCH requests will generally require a JSON formatted body be passed in the request.
GET Example with MATLAB
Continuing from the MATLAB example above to get the the Access token
%% Setup the options to do the various gets
options = weboptions('RequestMethod','get',...
'ContentType','json',...
'KeyName','Authorization',...
'KeyValue',['Bearer ',tokenRequestResponse.access_token]);
disp('');
disp('The options I need to pass for GET requests');
disp(options);
%% Get the sites i have in my account
disp('The sites I have in my account');
data= webread(...
'https://tqa.imageowl.com/api/rest/sites',...
'Accept','application/json',...
options);
tblSites = struct2table(data.sites)
%% What are the machine IDs associated with the first site in my account?
disp('What are the machine IDs associated with the first site in my account?');
firstID = data.sites(1).id;
machineData = webread(...
['https://tqa.imageowl.com/api/rest/machines?site=',int2str(firstID)],...
'Accept','application/json',...
options);
tblMachine = struct2table(machineData.machines,'AsArray',true)
GET Example with Python
A more complete example building on the Python example above that includes a GET call.
import json
import requests
class tqa_Connect:
def demo(self):
payload = {"client_id": "Your API Label",
"client_secret": "Your API Key",
"grant_type": "client_credentials"
}
r = requests.post('https://tqa.imageowl.com/api/rest/oauth',data = payload)
print 'Status Code:',r.status_code
j = r.json()
accessToken = j['access_token']
print 'Access Token: ',j['access_token']
bearerToken = 'Bearer ' + accessToken
url = "https://tqa.imageowl.com/api/rest/sites"
headers = {
'authorization': bearerToken,
'content-type': "application/json",
'accept': "application/json",
}
response = requests.request("GET", url, headers=headers)
print json.dumps(response.json(), indent=4, sort_keys=True)
tqa_Connect().demo()
GET Example with R
A more complete example building on the R example above that includes a GET call.
library(httr)
url <- 'http://tqa.imageowl.com/api/rest/oauth'
body <- list(client_id = 'Your API Label', client_secret= 'Your API Key',grant_type = 'client_credentials')
# get the access token in a respone
r <- POST(url, body = body, encode = "form")
tqa_token <- content(r,"parsed")
authorization <- paste('Bearer',tqa_token$access_token)
accept <- 'application/json'
tqa_headers <- c(Authorization= authorization,Accept = accept)
siteUrl <- 'https://tqa.imageowl.com/api/rest/sites'
s <- GET(siteUrl,add_headers(.headers = tqa_headers))
sites <- content(s,"parsed")
str(sites)
GET Example with C#
A complete example building on the C# example above that includes a GET call.
A utility class to hold the site information when it is returned.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Runtime.Serialization;
namespace TQA_API_Demo
{
[DataContract]
public class Site
{
[DataMember(Name= "id")]
public int ID { get; set; }
[DataMember(Name= "name")]
public String Name { get; set; }
[DataMember(Name= "notes")]
public String Notes { get; set; }
[DataMember(Name = "ownerId")]
public int OwnerID { get; set; }
[DataMember(Name = "machineIds")]
public List<int> MachineIds { get; set; }
[DataMember(Name = "userIds")]
public List<int> UserIds { get; set; }
}
[DataContract]
public class SiteList
{
[DataMember(Name = "sites")]
public List<Site> Sites { get; set; }
}
}
And now we use the access token to get the site information
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;
using Newtonsoft.Json; // uses the Json.NET assembly a freely available JSON library
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.IO;
namespace TQA_API_Demo
{
class Program
{
static void Main()
{
RunAsync().Wait();
}
static async Task RunAsync()
{
using (var client = new HttpClient())
{
// TODO - Send HTTP requests
Uri baseAddress = new Uri("https://tqadev.imageowl.com/");
client.BaseAddress = baseAddress;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var accessRequestData = new AccessRequest()
{
ClientID = "141:Webinar",
ClientSecret = "42d1a2b2277bbafc906b2a60744f2fb231757cef06df6e231a779093000b3e03",
GrantType = "client_credentials"
};
//HTTP get the access token
HttpResponseMessage response = await client.PostAsJsonAsync("api/rest/oauth", accessRequestData);
if (response.IsSuccessStatusCode)
{
accessRequestResponseData responseData = await response.Content.ReadAsAsync<accessRequestResponseData>();
Console.WriteLine("{0}\t{1}",responseData.AccessToken,responseData.ExpiresIn);
//Now that we have the access code let's get some data about the sites
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, "api/rest/sites");
requestMessage.Headers.Add("Authorization", "Bearer " + responseData.AccessToken);
response = await client.SendAsync(requestMessage);
string responseAsString = await response.Content.ReadAsStringAsync();
//prettify
Console.WriteLine(FormatJSON(responseAsString));
//turn the response into a list of Site objects
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(SiteList));
MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(responseAsString));
var obj = (SiteList)ser.ReadObject(stream);
Console.WriteLine("ID\tName\tMachine Ids\tUser Ids");
foreach (Site s in obj.Sites)
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}",
s.ID,
s.Name,
string.Join(",", s.MachineIds.ToArray()),
string.Join(",", s.UserIds.ToArray()));
}
}
Console.ReadLine();
}
}
private static string FormatJSON(string json)
{
dynamic parsedJson = JsonConvert.DeserializeObject(json);
return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}
}
}
MATLAB Wrapper for Smári API
A complete MATLAB wrapper for Total QA is available on GitHub (TQAConnector). The wrapper simplifies calls using MATLAB to the REST API and helps with some tasks that can be challenging even for experienced MATLAB experts.
Comments
0 comments
Please sign in to leave a comment.