
API Sample Code
tutorials

See the full swagger list of API methods here.
C# sample code
Download the complete example code here
Setup
All api calls should be inside the “using” statement
var client = new HttpClient())
{
client.BaseAddress = new Uri("api/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/json"));
}
Example of getting access tokens and using them to make a basic API call
private static string getAccessToken(HttpClient client, bool requiresUserToken)
{
string accessToken = null;
//check if the current access token has expired (this check should be done before any API call is made)
DateTime tokenExpiration = requiresUserToken ? UserTokenExpiration : AppTokenExpiration; //UserTokenExpiration and AppTokenExpiration should be application-level variables (may have been set from a previous request).
if (tokenExpiration <= DateTime.UtcNow)
{
//get an access token
var formContent;
if (requiresUserToken)
{
formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", "[account email]"),
new KeyValuePair<string, string>("password", "[password]"), //use SHA1 hash (base64-encoded string) of your password
new KeyValuePair<string, string>("client_id", "[your client id]")//You can find this in your account settings page
});
//Resources on SHA1 hashing:
https://stackoverflow.com/questions/40091771/sha-1-hashing-on-java-and-c-sharp
https://stackoverflow.com/questions/40740894/using-sha-1-in-net-core
}
else
{
formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", "[your client id]")//You can find this in your account settings page
});
}
HttpResponseMessage response = client.PostAsync("token", formContent).Result;
if (response.IsSuccessStatusCode)//request to get token was successful
{
//get access token and expiration from response
var responseJson = response.Content.ReadAsStringAsync().Result;
var jObject = JObject.Parse(responseJson);
accessToken = jObject.GetValue("access_token").ToString();
//note: "expires_in" is in seconds (typically the access token expiration is 30 minutes.)
DateTime expiration = DateTime.UtcNow.AddSeconds((double)Int32.Parse(jObject.GetValue("expires_in")));
if (requiresUserToken)
{
UserTokenExpiration = expiration;
}
else
{
AppTokenExpiration = expiration;
}
}
}
else
{
accessToken = requiresUserToken ? UserAccessToken : AppAccessToken; //use stored application-level variable from a previous request
}
return accessToken;
}
//make an API call with a token
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + getAccessToken(client, false));
response = client.GetAsync("Version").Result;
if (response.IsSuccessStatusCode) //API call was successful
{
string version = response.Content.ReadAsAsync<string>().Result;
}
Example of getting your company ID (or "CompanyVizSpaceID")
Using the User GET API
//note: this API requires an app access token to be included in the header
//for the password, use SHA1 hash (base64-encoded string) of the password
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + getAccessToken(client, false));
HttpResponseMessage response = client.GetAsync("User?emailID=" + userEmail + "&password=" + userPassword).Result;
UserProfile user = response.Content.ReadAsAsync<UserProfile>().Result;
string myCompanyId = user.CompanyVizSpaceID;
Example of adding a file
Using the File PUT API
//note: this API requires a user access token to be included in the header
string fileContent = Convert.ToBase64String([byte array of the file]);
//attributes are URL encoded. For this example, attributes would be "color%3Dred%26size%3Dlarge"
string attributes = HttpUtility.UrlEncode("color=red&size=large");
//add to company file database (attributes are optional)
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + getAccessToken(client, true));
HttpResponseMessage response = client.PutAsJsonAsync("File?file=exampleFile.png&isSearchInput=false&attributes=" + attributes, JsonConvert.SerializeObject(fileContent)).Result;
//or add just for search. Note: isSearchInput's default value is true;
HttpResponseMessage response = client.PutAsJsonAsync("File?file=.png", JsonConvert.SerializeObject(fileContent)).Result;
string fileUID = response.Content.ReadAsAsync<string>().Result; //get the id of the added file
//note: The File GET API can be used to get the details of an added file, as well as to check if the file has finished indexing, by looking at the "IndexingFinished" property.
Example of searching with a file
Using the Search GET and Search PUT APIs
//note: the Search APIs require a user access token to be included in the header
//with Search GET - using the file we just added using File PUT
//filterStr is URL encoded
string filterStr = HttpUtility.UrlEncode("fileUID=" + fileUID);
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + getAccessToken(client, true));
HttpResponseMessage response = client.GetAsync("Search?filterStr=" + filterStr).Result;
//or with Search PUT - using a new file
string[] byteArrays = new string[1];//multiple files could be used
byteArrays[0] = [byte array of the file];
HttpResponseMessage response = client.PutAsJsonAsync("Search?fileExtension=.png, JsonConvert.SerializeObject(byteArrays)).Result;
//using the search results. See the API Reference page for details about the SearchResultSummary object.
SearchResultSummary search = response.Content.ReadAsAsync<SearchResultSummary>().Result;
Python sample code
Download the complete example code here
Example of getting access tokens
def tokenJSON():
data = urllib.parse.urlencode({'grant_type': 'password', 'username': username, 'password': SHA1(password), 'client_id': clientid}) #replace the parameters with your own user name, password and client id
headers = {"Accept": "application/json;charset=UTF-8", "Content-Type": "application/x-www-form-urlencoded"}
h.request('POST', '/api/token', data, headers)
r = h.getresponse()
re = r.read()
print(re)
jsondata = json.loads(re)
token = jsondata.get('access_token')
return token
Example of adding a file
Using the File PUT API
def PUTFile(token):
headers = {"Accept": "application/json", "Authorization": "Bearer " + token,
"Content-Type": "application/json; charset=utf-8"}
base64String = json.dumps(b64())
URI = "/api/File?file=" + os.path.splitext(inputfile)[1] + "&isSearchInput=true"
h.request('PUT', URI, base64String, headers)
r = h.getresponse()
fileUID = r.read().decode("utf-8")
print(fileUID)
return fileUID
Example of searching with a file
Using the Search PUT API
def PUTSearch(token):
headers = {"Accept": "application/json", "Authorization": "Bearer " + token,
"Content-Type": "application/json; charset=utf-8"}
base64String = json.dumps(json.dumps([b64()]))
filterStr = "uid=" + companyID
filterStr = urllib.parse.quote(filterStr)
URI = "/api/Search?filterStr=" + filterStr + "&fileExtension=" + os.path.splitext(inputfile)[1]
h.request('PUT', URI, base64String, headers) # replace the uid parameter with your own company
r = h.getresponse()
print(r.read().decode("utf-8"))
Example of searching with a fileUID
C++ sample code
Download the complete example code here
Example of using MatchPosition to create a rotation matrix for aligning an input shape with a matching shape.
Using the Search GET API
def GETSearch(token, fileUID):
headers = {"Accept": "application/json", "Authorization": "Bearer " + token,
"Content-Type": "application/json; charset=utf-8"}
filterStr = "uid=" + companyID + "&fileUID=" + fileUID
filterStr = urllib.parse.quote(filterStr)
URI = "/api/Search?filterStr=" + filterStr
h.request('GET', URI, "", headers)
r = h.getresponse()
print(r.read().decode("utf-8"))
// foreground is the input image, assuming it's a drawing.
// background is a matching image (if it's a 3d view, the image needs to be 600x600).
bool AlignMatch(const wstring& basename, cv::Mat& foreground, cv::Mat& background, double offsetx, double offsety, double angle, double scale, cv::Mat& output)
{
// convert angle to degree
angle *= 180.0/iPI;
// Affine transformation order: scale first, then rotate, and finally translate
cv::Point2f center(foreground.cols / 2., foreground.rows / 2.);
// Create the transformation matrix
cv::Mat rotationMatrix = cv::getRotationMatrix2D(center, angle, scale);
// Calculate the bounding box size after transformation
cv::Rect2f bbox = cv::RotatedRect(cv::Point2f(), cv::Size2f(foreground.cols * scale, foreground.rows * scale), angle).boundingRect2f();
// Adjust the transformation matrix to account for translation
// 1. shift due to rotation center, 2. since offset is the center offset, we need to first align the two centers, 3. add the center offset
// center of foreground image after rotation and scalling
double centerx = bbox.width / 2.;
double centery = bbox.height / 2.;
rotationMatrix.at<double>(0, 2) += (bbox.width / 2.0 - center.x) + (background.cols/2.0 - centerx) + offsetx;
rotationMatrix.at<double>(1, 2) += (bbox.height / 2.0 - center.y) + (background.rows/2.0 - centery) + offsety;
// Make sure the output image is large enough
int outputW = max(int(bbox.width), background.cols);
int outputH = max(int(bbox.height), background.rows);
output = cv::Mat::zeros(outputH, outputW, background.type());
background.copyTo(output(cv::Rect(0,0,background.cols, background.rows)));
// WriteImage(basename+L"-o.png", output);
// Apply the affine transformation to the foreground image
cv::Mat transformedForeground = cv::Mat(output.size(), foreground.type(), {255, 255, 255});
cv::warpAffine(foreground, transformedForeground, rotationMatrix, transformedForeground.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT);
// WriteImage(basename+L"-w.png", transformedForeground);
// Create a mask from the transformed foreground image
cv::Mat mask;
cv::cvtColor(transformedForeground, mask, cv::COLOR_BGR2GRAY);
// WriteImage(basename+L"-gray.png", mask);
cv::threshold(mask, mask, 254, 255, cv::THRESH_BINARY_INV);
// WriteImage(basename+L"-mask.png", mask);
// Copy the transformed foreground image onto the background using the mask
transformedForeground.copyTo(output, mask);
return true;
}