Testify API Documentation
Table of contents
Overview
In our Technical Documentation the required information when working with the Testify API is listed.
The Testify API can be used to query information from Testify, but also to create and update information. With help of the Testify API it is easily possible to connect Testify to your own systems and exchange information in an automated way. Testify Webhooks can be used to respond on events that occur in Testify in an automated way (more information below).
The Testify API is a REST API which can be accessed via authenticated HTTP requests (using an API key). The documentation with all available endpoints can be found at https://cloud.testify.io/core/services/swagger/index.html and it is recommended to use the most recent version, which at the moment of writing this documentation is Testify API v3.0. Note that as of now all listed versions are supported, but it is not recommended to any other than v3.0 as the older versions might get deprecated in the future.
Fundamentals
HTTP Methods
StageBaseUrl
The StageBaseUrl can differ and must be adapted in the request URL (and also in the Swagger UI URL) if a private stage is used. All examples in this documentation use https://cloud.testify.io as StageBaseUrl and assume that the Testify stage is used.
To use endpoints from the public API you have to use the BaseUrl (https://cloud.testify.io) with /core/servies and follow up with the endpoint. In addition to that you have to define the https://testify.atlassian.net/wiki/spaces/TWN/pages/2185134081/Testify+API+Documentation#HTTP-Methods to be GET / POST or PATCH
Example of a complete URL for a GET request:
GET https://cloud.testify.io/core/services/public/testObjects/my-TestObject?api-version=3.0
Path Parameter vs. Query Parameter
The Parameters section in swagger shows the type of the parameter.
Path Parameter: /public/testObjects/my-testobject?api-version=3.0all path parameters are seperated by a
/
Query Paremeter: /public/testObjects/my-testobject?api-version=3.0the first query parameter must start with an
?all following query parameters are appended starting with an
&
Here also the three mandatory authentication HTTP headers are listed, for details see below section (Authentication).
Versioning
A version of the API contains a certain set of attributes, it is ensured that these are always available, the name of the attribute does not change and no new mandatory attributes are added in the same version. New optional fields are allowed, which can also affect the order of attributes.
Every HTTP request must contain the API version 3.0 as query parameter
e.g. ?api-version=3.0 or ?<other-parameter=value>&api-version=3.0
Main difference between V2 and V3:
| V2 | V3 |
|---|---|---|
IDs | Works with External IDs most of the time | User can choose between internal ID, external ID and identifier |
PATCH | ❌ Hardly supported | ✅ Supported at most entities |
Pagination | ❌ Not supported | ✅ Supported |
Check Results (POST) | ❌ Not supported | ✅ Supported for most check types |
Issues | ❌ Not supported | ✅ Supported |
Roles | ❌ Not supported | ✅ Supported |
Id, ExternalId, Identifier in Testify
The IDs of objects are handled differently in the different versions of the Public API.
Please have a look at the Version documentation on how to work with the different IDs.
Testify entities
Checklist Template: Defines the structure of a checklist with its pages, sections and checks.Checklist Instance: Is an instance of a checklist template which is assigned to a certain user or group and where check results are added. A checklist instance can be created from a published checklist template.Check&Check Result: A checklist can contain 13 different check types of checks with different parameters and result values. Adding a check result is only possible for following kinds of check types:
Issue&IssueCategory&IssueSeverity: An issue must be categorized and must have a severtiy.TestEquipment&TestEquipmentType: A testequipment is a tool that is used when executing a check and it is categorized by a test equipment type.TestObject&TestObjectType: A testobject can be linked to a checklist instance or an issue and it is categorized by a test object type.
Authentication
To access the Testify API a Testify user with a valid API key is needed. This API key must then be sent in every requests header.
Please be aware that a user in Testify has roles and permissions and is allowed to make certain requests based on that. An API key is always generated for a certain Testify user and when making a request with an API key the permissions of that user are used. Therefore, it is advised to create an own Interface User that has all roles and permissions needed for accessing the endpoints.
Create Interface User and generate API Key
Go to https://cloud.testify.io/todos and Log In with your regular account.
Go to “Administration” → “Users” and create a new Interface User with a self defined password and all roles assigned.
Within the User’s Profile, click on the context menu and select “Generate API key”.
Note the API key that consists of secret, Subject and Tenant.
Please be aware that this API key can only be viewed once and must be regenerated otherwise. Regenerating means disabling the previous used API key.
Authenticate with API Key
Place secret, Subject and Tenant in request header.
Webhooks
Webhooks allow you to respond on events that occur in Testify in an automated way, without the need to make requests repeatedly. To use webhooks a HTTP server where Testify is allowed to send POST requests is needed. When this is available, it can be easily configured within Testify on what events should be reacted to and to which URL the request should be sent to.
How to define a webhook within Testify
As logged in User go to “Administration” → “Workflows” and create a new Workflow.
Define a Name.
Define an Event.
Define an Action with scope “Webhook” and type “trigger”.
Click on “Parameters” and provide the URL of the webhook that should be called and can be accessed by Testify via
POSTrequest. As an optional parameter, an Identifier can be specified, which then will be sent in the request body. Also, the request timeout and the HTTP status codes that indicate success can be customized, as well as some authorization options containing of a secret and HTTP headers. Please consider thatContent-Type: application/jsonandContent-LengthHTTP headers are set implicitly as default by Testify and can't be added here.Save newly created workflow, which then automatically gets invoked when the specified event occurs.
To see when a webhook has been executed and whether the execution has been successful, go to the workflow details, click on the context menu and select “History”.
Samples of what information will be sent in the webhook payload
The HTTP method is always POST and the payload depends on the event that triggered the webhook.
Property | Description |
|---|---|
| This is set to the identifier that can be set as an optional parameter at the webhook configuration (see above). |
| Depending on the event that triggered the workflow these are set. |
| Id of the workflow that triggered the event. Only set if the event was triggered by a workflow. |
| Id of the tenant. |
| Gives information about the event that triggered the webhook: 1 (issue), 2 (checklist), 3 (testobject), 4 (pdf), 5 (user), or 6 (timertrigger). |
| Tells whether 1 (created) or 2 (updated) triggered the webhook. In our case a checklist has been created, so 1 is set. |
| Only set if the triggering event is an update event. Shows the values that were changed in this update. |
| External Id of the object that triggered the webhook. In our case this is the external id of the created checklist. |
| URL where details of the object that triggered the webhook can be found. In our case the created checklist can be queried via GET-request to this URL. |
| Date and time when the event took place. |
Here are some samples of sent information in the webhook payload:
Checklist created:
{
"WebHookIdentifier": null,
"IssueFilter": null,
"ChecklistFilter": {
"Id": "0878ec9e-62f1-4e65-be5c-42856f611420",
"ExternalId": "0878ec9e-62f1-4e65-be5c-42856f611420",
"CreatedById": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"ModifiedById": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"AssignedToId": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"TestObjectId": "34229f43-df5b-4d96-9a48-d1778ebf952b",
"TestObjectTypeId": "f4256bc1-400d-4bfe-9a4d-d3f48fd7fd7f",
"State": 0,
"ChecklistTemplateId": "f4a42636-995c-4231-bbf5-919909e40a69",
"ScheduledFor": "2022-04-04T22:00:00Z",
"Score": null,
"MaximumCheckScore": null
},
"TestObjectFilter": null,
"PdfFilter": null,
"UserFilter": null,
"TimerFilter": null,
"TriggeredByWorkflowId": null,
"TenantId": "0d629d72-3831-4874-8151-4b97f55523ff",
"EntityType": 2,
"Action": 1,
"ChangedValues": null,
"EntityId": "0878ec9e-62f1-4e65-be5c-42856f611420",
"EntityUrl": "https://cloud.testify.io/tests/0878ec9e-62f1-4e65-be5c-42856f611420/data",
"CreatedAt": "2022-04-04T10:23:27.3557053Z"
}Issue created:
Everything looks very similar to the checklist created event, but here the
IssueFilteris set andEntityTypeis set to 1 (issue).
{
"WebHookIdentifier": null,
"IssueFilter": {
"Id": "abb33d1f-6787-444b-b43f-aee7147c3d49",
"CreatedById": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"ModifiedById": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"AssignedToId": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"TestObjectId": "63be7657-2314-4704-b1d7-8de444f89039",
"TestObjectTypeId": "f4256bc1-400d-4bfe-9a4d-d3f48fd7fd7f",
"State": 1,
"IssueCategoryId": "c6246372-21df-49e5-b95e-073f000d775b",
"Severity": 2,
"Title": "test",
"Description": null,
"ScheduledFor": "2022-04-04T22:00:00Z"
},
"ChecklistFilter": null,
"TestObjectFilter": null,
"PdfFilter": null,
"UserFilter": null,
"TimerFilter": null,
"TriggeredByWorkflowId": null,
"TenantId": "0d629d72-3831-4874-8151-4b97f55523ff",
"EntityType": 1,
"Action": 1,
"ChangedValues": null,
"EntityId": "abb33d1f-6787-444b-b43f-aee7147c3d49",
"EntityUrl": "https://cloud.testify.io/issues/abb33d1f-6787-444b-b43f-aee7147c3d49",
"CreatedAt": "2022-04-04T10:30:26.5496694Z""
}Issue updated:
The issue has been resolved with a duration of 5 minutes.
Note the
ChangedValuesattribute that shows thatdurationandstatewere changed. AlsoActionhas value 2 (updated) now.
{
"WebHookIdentifier": null,
"IssueFilter": {
"Id": "d9507dd0-d767-4ab9-8bf2-dc9f6c37bf22",
"CreatedById": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"ModifiedById": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"AssignedToId": "4ee99e3e-04fd-4ded-b4c6-1463c7b6a157",
"TestObjectId": "34229f43-df5b-4d96-9a48-d1778ebf952b",
"TestObjectTypeId": "f4256bc1-400d-4bfe-9a4d-d3f48fd7fd7f",
"State": 2,
"IssueCategoryId": "c6246372-21df-49e5-b95e-073f000d775b",
"Severity": 2,
"Title": "test",
"Description": null,
"ScheduledFor": "2022-04-04T22:00:00Z"
},
"ChecklistFilter": null,
"TestObjectFilter": null,
"PdfFilter": null,
"UserFilter": null,
"TimerFilter": null,
"TriggeredByWorkflowId": null,
"TenantId": "0d629d72-3831-4874-8151-4b97f55523ff",
"EntityType": 1,
"Action": 2,
"ChangedValues": {
"duration": {
"oldValue": null,
"newValue": 5
},
"state": {
"oldValue": 1,
"newValue": 2
}
},
"EntityId": "d9507dd0-d767-4ab9-8bf2-dc9f6c37bf22",
"EntityUrl": "https://cloud.testify.io/issues/d9507dd0-d767-4ab9-8bf2-dc9f6c37bf22",
"CreatedAt": "2022-04-04T10:34:47.8509246Z"
}Authenticated webhook requests
As mentioned above additional parameters for sending authenticated webhook requests can be specified in the webhook “Parameters”. So the target of the webhook is able to verify the integrity of an incoming webhook request. This is possible by 2 differnt mechanisms:
Adding arbitrary HTTP-Headers: This consists of key-value pairs which are then sent in the HTTP headers, e.g. Username: {Username}, Password: {Password}. Please be aware that this should only be done when using a secure channel like HTTPS, TLS.
Signing the webhook request with a pre-shared secret: This adds the following two additional HTTP headers to the webhook request -
Testify-Webhook-SignatureandTestify-Webhook-Signature-Timestamp. TheTestify-Webhook-Signatureis a hashed value, which is created from a timestamp and the request payload by using SHA256 HMAC with the provided “secret” in the webhook parameters and then base64 encoding. Represented as:base64(HMACSHA256(TIMESTAMP + BODY))
To verify the signature, create the same SHA256 HMAC signature (containing of theTestify-Webhook-Signature-Timestampand the request payload) with the provided secret, then base64 encoding and compare it to theTestify-Webhook-Signaturesent in the request header. See following example:public bool VerifyWebhook([FromBody] object body) { var secret = "my-secret"; var signature = this.Request.Headers.GetValues("Testify-Webhook-Signature").FirstOrDefault(); var timestamp = this.Request.Headers.GetValues("Testify-Webhook-Signature-Timestamp").FirstOrDefault(); var parsedBody = JsonConvert.SerializeObject(body); using (var hmac = new HMACSHA256(Encoding.ASCII.GetBytes(secret))) { var encodedSignature = Convert.ToBase64String( hmac.ComputeHash( Encoding.ASCII.GetBytes($"{timestamp}{parsedBody}"))); return signature == encodedSignature; } }