Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Public

...

The purpose of this example is to setup a HTTP server that returns "Hello world". This server is then connected to Testify.

C#

Code Block
using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () =>
{
    return JsonSerializer.Serialize(new
    {
        text = "Hello world"
    });
});

app.Run();

Note:

  • This example is done using a C# Minimal API for simplicity, but similar functionality can also be achieved when using a more traditional ASP.NET API with controllers.

Python

Code Block
from flask import Flask
app = Flask(__name__)

@app.route("/")
def get_data():
    return {
        "text": "Hello world"
    }

if __name__ == "__main__":
    app.run()

Note:

  • This example uses flask which is a lightweight web framework. It can be installed with pip install Flask.

  • The last if is unnecessary if the python script is run with the command flask run. However, this takes more steps to setup which is why it hasn't been done here. For more information visit https://www.twilio.com/blog/how-run-flask-application . The script above works by simply running py FILENAME.py as you would expect.

Javascript

Code Block
import express from "express";
const app = express();

app.get("/", (req, res) => {
    res.json({
        "text": "Hello world"
    });
})

app.listen(3000, () => {
    console.log("Listening on port 3000");
});

Note:

  • This example uses express, which can be installed with npm install express.

Connecting the API to Testify

In order to make the "Hello World"-API that we created above accessible to Testify, we need to create a Public Device in the Testify web interface with the following options:

  • URL: depends on where you run your server

  • HTTP method: GET

  • HTTP headers: None

  • Check type: TextCheck

  • JSON path: $.text

Other check types

Depending on the check type, you need to send to provide data in a different format.

Public Devices

Public Devices need to be publicly accessible, so that Testify can send a request to it in case its value is needed by a checklist.

Technology

Any HTTP server with JSON responses can be used here. This means that any public API like weather APIs and others can act as Public Devices.

The structure of this JSON response can be very flexible, however it must be possible to decide which part of the JSON response (e.g. which property) should be used as a check result within Testify by specifying a JSON Path (see chapter "JSON paths").

Important: Make sure that this API is reachable on the Internet (e.g. have a public IP address or domain). Otherwise Testify will not be able to access it. The easiest way to test this is to try accessing this API with a different internet access than the one of your company (e.g. your private mobile phone).

Samples in some commonly used programming languages and frameworks can be found in Public Device Examples.

Connecting the API to Testify

Wheather you created your own API or use an existing one, you have to connect it to Testify . This can be done in the Testify web interface in Devices. If you create a Public Device there, you will need to provide:

  • URL: url of the API

  • HTTP method: what HTTP method should Testify use to make the request to the API. This is GET in most cases.

  • HTTP headers: any HTTP headers that Testify should send along with the request. This might be needed for an API-key.

  • Check type: what type of data you want to make accessible to Testify. For a list of available check types visit Overview.

For any check other than FileChecks or PhotoChecks :

  • JSON path: used to locate the exact value you want to provide to Testify. For more information see "Using JSON paths" below.

If you selected FileCheck or PhotoCheck, you have to use one of the following options instead of the JSON path mentioned above:

  • MIME type: enter the MIME type of the file or photo you want to send manually

  • JSON path to value: JSON path to the value you want to provide to Testify

    OR

  • JSON path to MIME type: JSON path to the MIME type

  • JSON path to value: JSON path to the value you want to provide to Testify

    OR (for FileChecksonly)

  • JSON path to file array: JSON path to the array of FileChecks. This array needs to have the following structure:

    Code Block
    [
        {
        	"value": YOUR_BASE64_STRING,
        	"mimeType": YOUR_MIME_TYPE
        },
        // other array elements here
    ]
    

Using JSON paths

JSON paths are used to extract a specific value from some JSON.

When accessing information from a public device, this JSON path tells Testify what information in the HTTP response it should use.

For example, if we have the following HTTP response:

Code Block
{
  "firstName": "Max",
  "lastName" : "Mustermann",
  "age"      : 26,
  "address"  : {
    "streetAddress": "Peter-Behrens-Platz 10",
    "city"         : "Linz",
    "postalCode"   : "4020"
  },
  "phoneNumbers": [
    {
      "type"  : "iPhone",
      "number": "0123456789"
    },
    {
      "type"  : "Home",
      "number": "0112233"
    }
  ]
}

And we want to get the value iPhone we can use the following JSON path:

Code Block
$.phoneNumbers[0].type

In the simplest case you might have a response like this:

Code Block
{
 	"temperature": 3.14159
}

And we would get the value 3.14159 like this:

Code Block
$.temperature

For more information on this concept visit https://jsonpath.com/ .

Registered Device Examples

This simple example sends the string "Hello world" to the Testify API as a TextCheck.

C#

...

Devices

Public Devices need to be publicly accessible, so that Testify can send a request to it in case its value is needed by a checklist.

Technology

Any HTTP server with JSON responses can be used here. This means that any public API like weather APIs and others can act as Public Devices.

The structure of this JSON response can be very flexible, however it must be possible to decide which part of the JSON response (e.g. which property) should be used as a check result within Testify by specifying a JSON Path (see chapter "JSON paths").

Important: Make sure that this API is reachable on the Internet (e.g. have a public IP address or domain). Otherwise Testify will not be able to access it. The easiest way to test this is to try accessing this API with a different internet access than the one of your company (e.g. your private mobile phone).

Samples in some commonly used programming languages and frameworks can be found in Public Device Examples.

Connecting the API to Testify

Wheather you created your own API or use an existing one, you have to connect it to Testify . This can be done in the Testify web interface in Devices. If you create a Public Device there, you will need to provide:

  • URL: url of the API

  • HTTP method: what HTTP method should Testify use to make the request to the API. This is GET in most cases.

  • HTTP headers: any HTTP headers that Testify should send along with the request. This might be needed for an API-key.

  • Check type: what type of data you want to make accessible to Testify. For a list of available check types visit Overview.

For any check other than FileChecks or PhotoChecks :

  • JSON path: used to locate the exact value you want to provide to Testify. For more information see "Using JSON paths" below.

If you selected FileCheck or PhotoCheck, you have to use one of the following options instead of the JSON path mentioned above:

  • MIME type: enter the MIME type of the file or photo you want to send manually

  • JSON path to value: JSON path to the value you want to provide to Testify

    OR

  • JSON path to MIME type: JSON path to the MIME type

  • JSON path to value: JSON path to the value you want to provide to Testify

    OR (for FileChecksonly)

  • JSON path to file array: JSON path to the array of FileChecks. This array needs to have the following structure:

    Code Block
    [
        {
        	"value": YOUR_BASE64_STRING,
        	"mimeType": YOUR_MIME_TYPE
        },
        // other array elements here
    ]
    

Using JSON paths

JSON paths are used to extract a specific value from some JSON.

When accessing information from a public device, this JSON path tells Testify what information in the HTTP response it should use.

...

For example, if we have the following HTTP response:

Code Block
{
  "firstName": "Max",
  "lastName" : "Mustermann",
  "age"      : 26,
  "address"  : {
    "streetAddress": "Peter-Behrens-Platz 10",
    "city"         : "Linz",
    "postalCode"   : "4020"
  },
  "phoneNumbers": [
    {
      "type"  : "iPhone",
      "number": "0123456789"
    },
    {
      "type"  : "Home",
      "number": "0112233"
    }
  ]
}

And we want to get the value iPhone we can use the following JSON path:

Code Block
$.phoneNumbers[0].type

...

In the simplest case you might have a response like this:

Code Block
{
 	"temperature": 3.14159
}

And we would get the value 3.14159 like this:

Code Block
$.temperature

...

For more information on this concept visit https://jsonpath.com/ .

Public Device Examples

The purpose of this example is to setup a HTTP server that returns "Hello world". This server is then connected to Testify.

C#

Code Block
using System.Text.Json;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () =>
{
    return JsonSerializer.Serialize(new
    {
        text = "Hello world"
    });
});

app.Run();

Note:

  • This example is done using a C# Minimal API for simplicity, but similar functionality can also be achieved when using a more traditional ASP.NET API with controllers.

Python

Code Block
from flask import Flask
app = Flask(__name__)

@app.route("/")
def get_data():
    return {
        "text": "Hello world"
    }

if __name__ == "__main__":
    app.run()

Note:

  • This example uses flask which is a lightweight web framework. It can be installed with pip install Flask.

  • The last if is unnecessary if the python script is run with the command flask run. However, this takes more steps to setup which is why it hasn't been done here. For more information visit https://www.twilio.com/blog/how-run-flask-application . The script above works by simply running py FILENAME.py as you would expect.

Javascript

Code Block
import express from "express";
const app = express();

app.get("/", (req, res) => {
    res.json({
        "text": "Hello world"
    });
})

app.listen(3000, () => {
    console.log("Listening on port 3000");
});

Note:

  • This example uses express, which can be installed with npm install express.

Connecting the API to Testify

In order to make the "Hello World"-API that we created above accessible to Testify, we need to create a Public Device in the Testify web interface with the following options:

  • URL: depends on where you run your server

  • HTTP method: GET

  • HTTP headers: None

  • Check type: TextCheck

  • JSON path: $.text

Other check types

Depending on the check type, you need to send to provide data in a different format.

Registered Devices

Registered Devices can send data to Testify at any time and it will be saved by Testify in case it is needed by a checklist.

Technology

The API is a public HTTP endpoint that accepts JSON data. Therefore any programming or scripting language capable of sending HTTP requests can be used to send data to the API.

Samples in some commonly used programming languages can be found in Registered Device Examples.

Access

The API is accessible at the following URL: https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE where CHECK_TYPE is the CheckType you want to send data for.

Authentication

You must include a deviceId with every API request. This deviceId can be created with the Testify web interface in Devices.

INSERT SCREENSHOT OR GIF OF HOW TO CREATE deviceId HERE

Request structure

There are 3 ways to add the deviceId to your HTTP request. Therefore, there are 3 different ways your HTTP request might look.

deviceId in Query-String

Add ?deviceId=YOUR_DEVICE_ID to the end of your request url.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE?deviceId=YOUR_DEVICE_ID HTTP/1.1
Content-Type: application/json

{
    "value": YOUR_VALUE
} 

deviceId as a HTTP-Header

Add a deviceId HTTP-Header with the value of YOUR_DEVICE_ID.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE HTTP/1.1
Content-Type: application/json
deviceId: YOUR_DEVICE_ID

{
    "value": YOUR_VALUE
}

deviceId in the HTTP-Body

Add a deviceId property to the JSON in the HTTP body.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/TextCheck?deviceId=YOUR_DEVICE_ID";
object payload = new { value = "Hello world" };

HttpContent httpContent = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var result = await client.PostAsync(url, httpContent);

Console.WriteLine(result.StatusCode);

Note:

  • The HttpClient should only be instantiated once (don't create a new one if you have to make multiple requests).

  • client.PostAsync is an asynchronous method which allows other code to run while we wait for the response. However, here we want to work with the result immidiately after the POST request, which is why await is used to force the program to wait for the response. In other scenarios (e.g. when having multiple API calls), removing await can lead to better performance.

Python

Code Block
import requests

url = "CHECK_TYPE HTTP/1.1
Content-Type: application/json

{
    "value": YOUR_VALUE,
    "deviceId": YOUR_DEVICE_ID
}

Note:

  • value is the actual value that you want to send to the API. This varies depending on the check type.

Custom timestamp

By default Testify uses the timestamp of the HTTP request as a creationDate. However, if the time you get data from your sensor and the time you send it to the API vary, you might consider adding a creationDate manually.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/TextCheckCHECK_TYPE?deviceId=YOUR_DEVICE_ID" payload = { "value": "Hello world" }

response = requests.post(url = url, json = payload, headers={"Content-Type": "application/json"})

print(response.status_code)

Note:

  • The library requests has to be installed for this to work. It can be installed using pip install requests.

Javascript

Code Block
let url = "HTTP/1.1
Content-Type: application/json

{
    "value": YOUR_VALUE,
    "creationDate": YOUR_CUSTOM_CREATION_DATE
}

Adding MIME types to the Request

For FileChecks and PhotoChecks you need to add the MIME type to the request. There are 2 ways to do that:

With an additional property

The easiest way is to add the property valueMimeType to the http request and specify the appropriate MIME type there.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/TextCheckCHECK_TYPE?deviceId=YOUR_DEVICE_ID";
let payload = { "value": "Hello world" };

fetch(url, HTTP/1.1
Content-Type: application/json

{
    method: "POSTvalue",: {
   headers: { "Content-Type	"value": "application/json" }YOUR_BASE64_STRING,
    body: JSON.stringify(payload)
}).then((response) => {
    console.log(response.status);
})

Note:

  • When Javascript is run in a browser fetch is available by default. However, if we want to run it in Node.js we have to install it first by running npm install node-fetch and importing it at the top of our file with import fetch from "node-fetch".

  • fetch returns a Promise, which can be handled with then like in the example above or with async/await. For more information visit https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/async_function .

Curl

Code Block
curl -X POST -i -H "	"mimeType": YOUR_MIME_TYPE
    }
}

With a data URL

Another way to add the MIME type to the request is to use a data URL instead of standard base64-string.

Data urls are essentially base64-strings with MIME-types attached to them. For example:

Code Block
data:YOUR_MIME_TYPE;base64,YOUR_BASE64_STRING

So with this data URL, your request could look like this:

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE?deviceId=YOUR_DEVICE_ID HTTP/1.1
Content-Type: application/json"
-d
"{\
    "value\": \"Hello world\"}" https://externaldatastore.azurewebsites.net/api/device/TextCheck?deviceId=YOUR_DEVICE_ID

Note for all of the examples above:

  • YOUR_DEVICE_ID needs to be replaced with your specific deviceId. Information on how to get this can be found at [Authentication in Registered Devices](Registered Devices.md).

Other authentication methods

If you don't want to add your deviceId as a query parameter at the end of the url like in the example above, you can also use one of the following two approaches:

deviceId as a HTTP-Header

deviceId is added as a HTTP header with the value of YOUR_DEVICE_ID.

Code Block
HttpContent httpContent = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
httpContent.Headers.Add("deviceId", YOUR_DEVICE_ID);
Code Block
response = requests.post(url = url, json = payload, headers={
    "Content-Type": "application/json",
    "deviceId": YOUR_DEVICE_ID
})
Code Block
fetch(url, {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "deviceId": YOUR_DEVICE_ID
    },
    body: JSON.stringify(payload)
}).then((response) => {
    console.log(response.status);
});

deviceId in the HTTP-Body

deviceId is added in the payload of the HTTP request.

Code Block
object payload = new {
    value = YOUR_VALUE,
    deviceId = YOUR_DEVICE_ID
});
Code Block
payload = { 
    "value": YOUR_VALUE, 
    "deviceId": YOUR_DEVICE_ID
}
Code Block
let payload = { 
    "value": YOUR_VALUE, 
    "deviceId": YOUR_DEVICE_ID
};

Other check types

Depending on the check type, the value you send to the API has to be of a certain type (see Available check types in Overview). Here are some examples using all the different check types in different programming languages.

TextCheck

Code Block
string text = "Hello";
Code Block
text = "Hello"
Code Block
let text = "Hello";

NumericCheck

Code Block
double number = 3.14159;
Code Block
number = 3.14159
Code Block
let number = 3.14159;

LogicCheck

Code Block
bool logic = false;
Code Block
logic = False
Code Block
let logic = false;

SingleChoiceCheck

Here you need to provide the GUID of the choice from the single choice check that we want to select.

Code Block
string singleChoice = "e0607e71-56c6-4a62-9112-ce0eab4cdcf5";
Code Block
single_choice = "e0607e71-56c6-4a62-9112-ce0eab4cdcf5"
Code Block
let singleChoice = "e0607e71-56c6-4a62-9112-ce0eab4cdcf5";

MultipleChoiceCheck

Here you need to provide the GUID of the choices from the multiple choice check that we want to select.

Code Block
string[] multipleChoices = new string[] { "e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdcf3" };
Code Block
multiple_choices = ["e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdcf3"]
Code Block
let multipleChoices = ["e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdcf3"];

TestobjectSelection

Here you need to provide the GUID of the test objects you want to select.

Code Block
string[] testObject = new string[] { "e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdc32" };
Code Block
test_object = ["e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdc32"]
Code Block
let testObject = ["e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdc32"];

TimeCheck

If you use language that doesn't allow you to create a Timeonly datatype (Javascript) or where the serializer doesn't support the Timeonly type yet (C#), you have 2 options:

  • Create a normal Date (Javascript) or DateTime (C#) object and enter random values for the date (the date will be ignored by the Testify API).

  • Send a string representation of the time you want.

Code Block
DateTime time = new DateTime(1970, 1, 1, 20, 15, 33, 0);
string timeAsString = "20:15:33";
Code Block
time = datetime.time(20, 15, 33, 0).__str__()
Code Block
let time = new Date(1970, 1, 1, 20, 15, 33, 0);
let timeAsString = "20:15:33";

DateCheck

Code Block
DateTime date = new DateTime(2021, 12, 24);
Code Block
date = datetime.date(2021, 12, 24).__str__()
Code Block
let date = new Date(2021, 12, 24);

FileCheck

FileChecks are somewhat different from other checks:

  • You can send multiple files with one request (notice that a list of objects is used).

  • You have to provide a mime type for every file. For a list of all allowed mime types visit Allowed MIME types for FileChecks.

Code Block
string fileDataBase64 = Convert.ToBase64String(File.ReadAllBytes("./assets/file.zip"));
object[] fileDataList = new[] {
    new
    {
        value = fileDataBase64,
        mimeType = "application/zip"
    }
};
Code Block
file_data = open("./assets/file.zip", "rb").read()
file_data_base64 = base64.b64encode(file_data).decode("utf-8") # .decode("utf-8") so that it's a string
file_data_list = [
    {
        "value": file_data_base64,
        "mimeType": "application/zip"
    }
]
Code Block
let fileDataBase64 = await fs.readFile("./assets/file.zip", { encoding: 'base64' });
let fileDataList = [
    {
        "value": fileDataBase64,
        "mimeType": "application/zip"
    }
];

PhotoCheck

Photo are somewhat different from other checks, as you have to provide a mime type for every photo you send to the API. For a list of all allowed mime types visit Allowed MIME types for PhotoChecks.

Code Block
string photoDataBase64 = Convert.ToBase64String(File.ReadAllBytes("./assets/photo.png"));
object photoDataObject = new
{
    value = photoDataBase64,
    mimeType = "image/png"
};
Code Block
photo_data = open("./assets/photo.png", "rb").read()
photo_data_base64 = base64.b64encode(photo_data).decode("utf-8") # .decode("utf-8") so that it's a string
photo_data_object = {
    "value": photo_data_base64,
    "mimeType": "image/png"
}
Code Block
let photoDataBase64 = await fs.readFile("./assets/photo.png", { encoding: 'base64' });
let photoDataObject = {
    "value": photoDataBase64,
    "mimeType": "image/png"
};

Notice that we don't use a list here like we do with FileChecks.

Registered Devices

Registered Devices can send data to Testify at any time and it will be saved by Testify in case it is needed by a checklist.

Technology

The API is a public HTTP endpoint that accepts JSON data. Therefore any programming or scripting language capable of sending HTTP requests can be used to send data to the API.

Samples in some commonly used programming languages can be found in Registered Device Examples.

Access

The API is accessible at the following URL: https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE where CHECK_TYPE is the CheckType you want to send data for.

Authentication

You must include a deviceId with every API request. This deviceId can be created with the Testify web interface in Devices.

INSERT SCREENSHOT OR GIF OF HOW TO CREATE deviceId HERE

Request structure

There are 3 ways to add the deviceId to your HTTP request. Therefore, there are 3 different ways your HTTP request might look.

deviceId in Query-String

Add ?deviceId=YOUR_DEVICE_ID to the end of your request url.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE?deviceId=YOUR_DEVICE_ID HTTP/1.1
Content-Type: application/json

{
    "value": YOUR_VALUE
} 

deviceId as a HTTP-Header

Add a deviceId HTTP-Header with the value of YOUR_DEVICE_ID.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE HTTP/1.1
Content-Type: application/json
deviceId: YOUR_DEVICE_ID

{
    "value": YOUR_VALUE
}

deviceId in the HTTP-Body

Add a deviceId property to the JSON in the HTTP body.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE HTTP/1.1
Content-Type: application/json

{
    "value": YOUR_VALUE,
    "deviceId": YOUR_DEVICE_ID
}

Note:

  • value is the actual value that you want to send to the API. This varies depending on the check type.

Custom timestamp

By default Testify uses the timestamp of the HTTP request as a creationDate. However, if the time you get data from your sensor and the time you send it to the API vary, you might consider adding a creationDate manually.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE?deviceId=YOUR_DEVICE_ID HTTP/1.1
Content-Type: application/json

{
    "value": YOUR_VALUE,
    "creationDate": YOUR_CUSTOM_CREATION_DATE
}

Adding MIME types to the Request

For FileChecks and PhotoChecks you need to add the MIME type to the request. There are 2 ways to do that:

With an additional property

The easiest way is to add the property valueMimeType to the http request and specify the appropriate MIME type there.

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE?deviceId=YOUR_DEVICE_ID HTTP/1.1
Content-Type: application/json

{
    "value": {
    	"value": YOUR_BASE64_STRING,
    	"mimeType": YOUR_MIME_TYPE
    }
}

With a data URL

Another way to add the MIME type to the request is to use a data URL instead of standard base64-string.

Data urls are essentially base64-strings with MIME-types attached to them. For example:

Code Block
data:YOUR_MIME_TYPE;base64,YOUR_BASE64_STRING

So with this data URL, your request could look like this:

Code Block
POST https://externaldatastore.azurewebsites.net/api/device/CHECK_TYPE?deviceId=YOUR_DEVICE_ID HTTP/1.1
Content-Type: application/json

{
    "value": {
    	"value": YOUR_DATA_URL
    }
}

Note:

  • CHECK_TYPE is either FileCheck or PhotoCheck

  • YOUR_BASE64_STRING is the base64-representation of the file or image you want to send

  • YOUR_MIME_TYPE is one of the allowed MIME types listed in Overview

Response status codes

After sending data to the Testify API, you can look at the HTTP status code of the response to determine wheater your request was successful or failed. If a request failed, status codes can provide additional information on why it failed.

...

HTTP Status Code

...

Explanation

...

201 - Created

...

Everything worked as expected.

...

400 - Bad Request

...

Some required parameters are not provided.

...

401 - Unauthorized

...

The provided deviceId doesn't seem to exist.

...

422 - Unprocessable Entity

...

{
    	"value": YOUR_DATA_URL
    }
}

Note:

  • CHECK_TYPE is either FileCheck or PhotoCheck

  • YOUR_BASE64_STRING is the base64-representation of the file or image you want to send

  • YOUR_MIME_TYPE is one of the allowed MIME types listed in Overview

Response status codes

After sending data to the Testify API, you can look at the HTTP status code of the response to determine wheater your request was successful or failed. If a request failed, status codes can provide additional information on why it failed.

HTTP Status Code

Explanation

201 - Created

Everything worked as expected.

400 - Bad Request

Some required parameters are not provided.

401 - Unauthorized

The provided deviceId doesn't seem to exist.

422 - Unprocessable Entity

The shape of the JSON body isn't right or the mime type doesn't match the file or photo that was sent

Registered Device Examples

This simple example sends the string "Hello world" to the Testify API as a TextCheck.

C#

Code Block
HttpClient client = new HttpClient();

string url = "https://externaldatastore.azurewebsites.net/api/device/TextCheck?deviceId=YOUR_DEVICE_ID";
object payload = new { value = "Hello world" };

HttpContent httpContent = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
var result = await client.PostAsync(url, httpContent);

Console.WriteLine(result.StatusCode);

Note:

  • The HttpClient should only be instantiated once (don't create a new one if you have to make multiple requests).

  • client.PostAsync is an asynchronous method which allows other code to run while we wait for the response. However, here we want to work with the result immidiately after the POST request, which is why await is used to force the program to wait for the response. In other scenarios (e.g. when having multiple API calls), removing await can lead to better performance.

Python

Code Block
import requests

url = "https://externaldatastore.azurewebsites.net/api/device/TextCheck?deviceId=YOUR_DEVICE_ID"
payload = { "value": "Hello world" }

response = requests.post(url = url, json = payload, headers={"Content-Type": "application/json"})

print(response.status_code)

Note:

  • The library requests has to be installed for this to work. It can be installed using pip install requests.

Javascript

Code Block
let url = "https://externaldatastore.azurewebsites.net/api/device/TextCheck?deviceId=YOUR_DEVICE_ID";
let payload = { "value": "Hello world" };

fetch(url, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(payload)
}).then((response) => {
    console.log(response.status);
})

Note:

  • When Javascript is run in a browser fetch is available by default. However, if we want to run it in Node.js we have to install it first by running npm install node-fetch and importing it at the top of our file with import fetch from "node-fetch".

  • fetch returns a Promise, which can be handled with then like in the example above or with async/await. For more information visit https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Statements/async_function .

Curl

Code Block
curl -X POST -i -H "Content-Type: application/json" -d "{\"value\": \"Hello world\"}" https://externaldatastore.azurewebsites.net/api/device/TextCheck?deviceId=YOUR_DEVICE_ID

...

Note for all of the examples above:

  • YOUR_DEVICE_ID needs to be replaced with your specific deviceId. Information on how to get this can be found at [Authentication in Registered Devices](Registered Devices.md).

Other authentication methods

If you don't want to add your deviceId as a query parameter at the end of the url like in the example above, you can also use one of the following two approaches:

deviceId as a HTTP-Header

deviceId is added as a HTTP header with the value of YOUR_DEVICE_ID.

Code Block
HttpContent httpContent = new StringContent(JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
httpContent.Headers.Add("deviceId", YOUR_DEVICE_ID);
Code Block
response = requests.post(url = url, json = payload, headers={
    "Content-Type": "application/json",
    "deviceId": YOUR_DEVICE_ID
})
Code Block
fetch(url, {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "deviceId": YOUR_DEVICE_ID
    },
    body: JSON.stringify(payload)
}).then((response) => {
    console.log(response.status);
});

deviceId in the HTTP-Body

deviceId is added in the payload of the HTTP request.

Code Block
object payload = new {
    value = YOUR_VALUE,
    deviceId = YOUR_DEVICE_ID
});
Code Block
payload = { 
    "value": YOUR_VALUE, 
    "deviceId": YOUR_DEVICE_ID
}
Code Block
let payload = { 
    "value": YOUR_VALUE, 
    "deviceId": YOUR_DEVICE_ID
};

Other check types

Depending on the check type, the value you send to the API has to be of a certain type (see Available check types in Overview). Here are some examples using all the different check types in different programming languages.

TextCheck

Code Block
string text = "Hello";
Code Block
text = "Hello"
Code Block
let text = "Hello";

NumericCheck

Code Block
double number = 3.14159;
Code Block
number = 3.14159
Code Block
let number = 3.14159;

LogicCheck

Code Block
bool logic = false;
Code Block
logic = False
Code Block
let logic = false;

SingleChoiceCheck

Here you need to provide the GUID of the choice from the single choice check that we want to select.

Code Block
string singleChoice = "e0607e71-56c6-4a62-9112-ce0eab4cdcf5";
Code Block
single_choice = "e0607e71-56c6-4a62-9112-ce0eab4cdcf5"
Code Block
let singleChoice = "e0607e71-56c6-4a62-9112-ce0eab4cdcf5";

MultipleChoiceCheck

Here you need to provide the GUID of the choices from the multiple choice check that we want to select.

Code Block
string[] multipleChoices = new string[] { "e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdcf3" };
Code Block
multiple_choices = ["e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdcf3"]
Code Block
let multipleChoices = ["e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdcf3"];

TestobjectSelection

Here you need to provide the GUID of the test objects you want to select.

Code Block
string[] testObject = new string[] { "e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdc32" };
Code Block
test_object = ["e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdc32"]
Code Block
let testObject = ["e0607e71-56c6-4a62-9112-ce0eab4cdcf5", "e0607e71-56c6-4a62-9112-ce0eab4cdc32"];

TimeCheck

If you use language that doesn't allow you to create a Timeonly datatype (Javascript) or where the serializer doesn't support the Timeonly type yet (C#), you have 2 options:

  • Create a normal Date (Javascript) or DateTime (C#) object and enter random values for the date (the date will be ignored by the Testify API).

  • Send a string representation of the time you want.

Code Block
DateTime time = new DateTime(1970, 1, 1, 20, 15, 33, 0);
string timeAsString = "20:15:33";
Code Block
time = datetime.time(20, 15, 33, 0).__str__()
Code Block
let time = new Date(1970, 1, 1, 20, 15, 33, 0);
let timeAsString = "20:15:33";

DateCheck

Code Block
DateTime date = new DateTime(2021, 12, 24);
Code Block
date = datetime.date(2021, 12, 24).__str__()
Code Block
let date = new Date(2021, 12, 24);

FileCheck

FileChecks are somewhat different from other checks:

  • You can send multiple files with one request (notice that a list of objects is used).

  • You have to provide a mime type for every file. For a list of all allowed mime types visit Allowed MIME types for FileChecks.

Code Block
string fileDataBase64 = Convert.ToBase64String(File.ReadAllBytes("./assets/file.zip"));
object[] fileDataList = new[] {
    new
    {
        value = fileDataBase64,
        mimeType = "application/zip"
    }
};
Code Block
file_data = open("./assets/file.zip", "rb").read()
file_data_base64 = base64.b64encode(file_data).decode("utf-8") # .decode("utf-8") so that it's a string
file_data_list = [
    {
        "value": file_data_base64,
        "mimeType": "application/zip"
    }
]
Code Block
let fileDataBase64 = await fs.readFile("./assets/file.zip", { encoding: 'base64' });
let fileDataList = [
    {
        "value": fileDataBase64,
        "mimeType": "application/zip"
    }
];

PhotoCheck

Photo are somewhat different from other checks, as you have to provide a mime type for every photo you send to the API. For a list of all allowed mime types visit Allowed MIME types for PhotoChecks.

Code Block
string photoDataBase64 = Convert.ToBase64String(File.ReadAllBytes("./assets/photo.png"));
object photoDataObject = new
{
    value = photoDataBase64,
    mimeType = "image/png"
};
Code Block
photo_data = open("./assets/photo.png", "rb").read()
photo_data_base64 = base64.b64encode(photo_data).decode("utf-8") # .decode("utf-8") so that it's a string
photo_data_object = {
    "value": photo_data_base64,
    "mimeType": "image/png"
}
Code Block
let photoDataBase64 = await fs.readFile("./assets/photo.png", { encoding: 'base64' });
let photoDataObject = {
    "value": photoDataBase64,
    "mimeType": "image/png"
};

Notice that we don't use a list here like we do with FileChecks.

Info

For the functionality in Testify, key users can find more information at Equipment or Messmittel.