Skip to main content

Web API

Testspace provides a REST API, designed to have predictable, resource-oriented URLs that leverage built-in features of HTTP, like authentication, verbs and response codes. All data is sent and received in JSON format and UTF-8 encoding. Any off-the-shelf HTTP client can be used to communicate with the API.

This API is not for publishing test results. The Testspace client is required for pushing data to the server.

Overview​

Authentication​

Testspace API is authenticated using HTTP Basic Auth over HTTPS. Always use https://: a plain HTTP request is redirected, but only after its credentials were sent unencrypted.

The credentials may be given either as username:password or as access-token: (You can generate and get an Access token from your user settings).

For example using curl you can pass the -u flag:

$ curl -u <username:password> "https://domain.testspace.com/api/projects"
$ curl -u <access-token:> "https://domain.testspace.com/api/projects"

or set the Authorization header:

$ curl -H "Authorization: Token <access-token>" "https://domain.testspace.com/api/projects"

All requests are associated with a specific user in Testspace and permissions are limited to that user's capabilities.

Requests​

The base URL of the API is https://domain.testspace.com/api where domain should be replaced with your organization subdomain.

Parameters​

Many API methods take optional parameters. For GET requests, any parameters not specified as a segment in the path can be passed as an HTTP query string parameter:

$ curl -u username:password "https://domain.testspace.com/api/projects/123/spaces/1234/results?name=MyResult"

In this example, the values '123' and '1234' are provided for the project :project_id and space :space_id parameters in the path, while name is passed in the query string.

For POST, PATCH, PUT, and DELETE requests, parameters not included in the URL are sent as JSON, with a Content-Type of application/json. A request whose Accept header asks for something other than JSON gets 415 Unsupported Media Type:

$ curl -u username:password "https://domain.testspace.com/api/spaces/1234" \
-X PATCH \
-H 'Content-Type: application/json' \
-d '{"description":"some description"}'

HTTP Verbs​

The API strives to use appropriate HTTP verbs for each action:

  • GET - To retrieve a resource or a collection of resources
  • POST - To create a resource
  • PATCH or PUT - To modify a resource
  • DELETE - To delete a resource

Responses​

All response bodies, including errors, are JSON encoded with a Content-Type of application/json.

A single resource is represented as a JSON object:

{
"field1": "value",
"field2": true,
"field3": []
}

A collection of resources is represented as a JSON array of objects:

[
{
"field1": "value",
"field2": true,
"field3": []
},
{
"field1": "another value",
"field2": false,
"field3": []
}
]

All timestamps are returned in ISO 8601 format.

Unset fields will be represented as a null instead of being omitted. If the field is an array, it will be represented as an empty array - i.e. [].

Errors​

The API uses HTTP status codes to indicate success or failure of a request. In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that resulted from the provided information (e.g. authentication failed, a resource not found, a validation error, etc.), and codes in the 5xx range indicate an internal server error.

4xx series errors are returned with a JSON object in the body, except 415 Unsupported Media Type:

{
"message": "Page not found"
}

5xx series error codes do not return JSON bodies.

Pagination​

Listing resources will be paginated to 30 items by default. To control that you can pass the following parameters:

parameterdescription
pagePage number (default: 1)
per_pageNumber of items to list per page (default: 30, max: 100)

For example to list 50 projects per page:

$ curl -u username:password "https://domain.testspace.com/api/projects?per_page=50"

A Link header is sent back with each response. It has a rel set to prev/next/first/last and contains the relevant URL. Follow these links instead of constructing your own URLs: a page past the last one returns 500, not an empty list. The Total-Count and Total-Pages headers give the size of the whole collection.

The Result failures and Result issues lists are not paginated: each returns the whole list.

Projects​

All the information in Testspace is organized in Projects. A project contains one or more Spaces.

FieldTypeNotes
idintegerThe unique ID of the project
namestringThe name of the project
descriptionstringThe description of the project
is_privatebooleanTrue if the project is private, false otherwise
archivedbooleanTrue if the project is archived, false otherwise
source_repo_urlstringThe URL of the repo if connected project
issues_providerstringThe selected issues provider: generic, github:org/repo, gitlab:org/repo, bitbucket:org/repo or jira:site/KEY
push_tokenstringThe project's specific token for results pushing (only available to admin users)
spaces_urlstringThe URL of the contained Spaces list API
created_attimestampThe date/time when the project was created
updated_attimestampThe date/time when the project was last updated

To request details about projects and to create or modify projects use the following API methods.

List projects​

GET /api/projects
parameterdescription
nameOptional query parameter: lists only the projects with this name

A successful response includes an array of projects, ordered by name, as each entry in the list follows the same format as get a project:

200 OK
Content-Type: application/json
[
{ "id": 123, "name": "..." },
{ "id": 345, "name": "..." },
]

Get a project​

GET /api/projects/:project_id
parameterdescription
:project_idThe name or the ID of a project. A Connected Project can also be given as service:org/repo (e.g. github:myorg/myrepo)

A successful response looks like:

200 OK
Content-Type: application/json
{
"id": 123,
"name": "MyProject",
"description": "Some description for my project",
"is_private": true,
"archived": false,
"source_repo_url": null,
"issues_provider": "generic",
"push_token": "tsp_0123456789abcdef0123456789abcdef01234567",
"spaces_url": "https://myorg.testspace.com/api/projects/123/spaces",
"created_at": "2014-10-06T18:02:54Z",
"updated_at": "2014-12-04T19:59:42Z"
}

Create a project​

POST /api/projects

Only Organization admins can create a project.

FieldRequiredNotes
nameyesThe name of the project
descriptionnoThe description of the project
is_privatenoTrue (default) if the project is private, false otherwise
source_reponoFor connected projects creation only! The source repo identifier, formatted as service:org/repo, where service is github, bitbucket or gitlab

Sample request:

POST /api/projects
Content-Type: application/json
{
"name": "MyProject",
"description": "Some description for my project",
"...": "..."
}

A successful response returns the new project following the same format as get a project:

201 Created
Location: https://domain.testspace.com/api/projects/123
Content-Type: application/json
{
"id": 123,
"name": "MyProject",
"...": "..."
}

Update a project​

PATCH /api/projects/:project_id
PUT /api/projects/:project_id

Only Organization admins can update a project.

parameterdescription
:project_idThe name or the ID of a project
FieldRequiredNotes
namenoThe name of the project
descriptionnoThe description of the project
is_privatenoTrue if the project is private, false otherwise
archivednoTrue to archive the project, false to restore it
issues_providernoThe issues provider, in the same form as the issues_provider field

Sample request:

PATCH /api/projects/123
Content-Type: application/json
{
"name": "NewProject",
"...": "..."
}

A successful response returns no content:

205 Reset Content

Delete a project​

DELETE /api/projects/:project_id
parameterdescription
:project_idThe name or the ID of a project

Sample request:

DELETE /api/projects/123

A successful response returns no content:

204 No Content

Spaces​

Each Project consists of Spaces. A Space is a collection of test Results and Metrics.

FieldTypeNotes
idintegerThe unique ID of the space
namestringThe name of the space
descriptionstringThe description of the space
typestringIn a Connected Project: branch, fork (a pull request's Space, named PR-n), tags or manual. In a Standalone Project: manual for a Space with Manual testing, otherwise null
manualbooleanTrue if the space has Manual testing enabled, false otherwise
project_idintegerThe associated project
sandboxbooleanTrue if the space is a sandbox, false otherwise
result_set_aggregationbooleanTrue if the space aggregates its results (see Show), false otherwise
stalebooleanTrue if the space's pull request was closed or its project was disconnected, false otherwise
min_run_periodintegerPublication deadline for results in days (0 to disable)
active_result_set_idintegerThe ID of the space's active (latest complete) result
latest_result_set_idintegerThe ID of the space's latest result
results_urlstringThe URL of the contained Results list API
metrics_urlstringThe URL of the contained Metrics list API
created_attimestampThe date/time when the space was created
updated_attimestampThe date/time when the space was last updated

To request details about spaces and to create or modify spaces use the following API methods.

List spaces​

GET /api/projects/:project_id/spaces

Lists the Spaces as the Spaces listing does: newest Result first, then by name, without stale Spaces. In a Connected Project, a branch with no complete Result is left out, unless it has Manual testing or is the default branch.

parameterdescription
:project_idThe name or the ID of the associated project

A successful response includes an array of spaces, as each entry in the list follows the same format as Get a space:

200 OK
Content-Type: application/json
[
{ "id": 1234, "name": "..." },
{ "id": 5678, "name": "..." },
]

To get one space by its name, use Get a space with the project in the path.

Get a space​

GET /api/spaces/:space_id
parameterdescription
:space_idThe ID of a space
GET /api/projects/:project_id/spaces/:space_id
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe ID or the URL-encoded name of a space

A successful response looks like:

200 OK
Content-Type: application/json
{
"id": 1234,
"name": "MySpace",
"description": "Some description for my space",
"type": null,
"manual": false,
"project_id": 12,
"sandbox": false,
"result_set_aggregation": false,
"stale": false,
"min_run_period": 1,
"active_result_set_id": 10823,
"latest_result_set_id": 10823,
"results_url": "https://myorg.testspace.com/api/projects/12/spaces/1234/results",
"metrics_url": "https://myorg.testspace.com/api/projects/12/spaces/1234/metrics",
"created_at": "2014-10-06T18:02:54Z",
"updated_at": "2014-12-04T19:59:42Z"
}

Create a space​

POST /api/projects/:project_id/spaces

Only in a Standalone Project: a Connected Project's Spaces follow its repository, and the request returns 403.

parameterdescription
:project_idThe name or the ID of the associated project
FieldRequiredNotes
nameyesThe name of the space
descriptionnoThe description of the space
sandboxnoTrue for a sandbox space, false (default) otherwise
min_run_periodnoPublication deadline for results in days (0 to disable)
result_set_aggregationnoTrue for a space that aggregates its results; false by default, true for a Manual space
manualnoStandalone Projects only: true to enable Manual testing
publish_pathnoStandalone Projects only: where the space's Manual results are placed in the Suite tree (see Publish Path)
basenoThe name of an existing Space to copy settings from (see Copy Settings)
Nest the fields under space

manual and base are read only inside a space object; sent at the top level, they are ignored, and the Space is created without Manual testing or copied settings. Send every field inside space:

Sample request:

POST /api/projects/12/spaces
Content-Type: application/json
{
"space": {
"name": "MySpace",
"description": "Some description for my space",
"manual": true,
"base": "main"
}
}

A successful response returns the new space following the same format as Get a space:

201 Created
Location: https://domain.testspace.com/api/projects/12/spaces/1234
Content-Type: application/json
{
"id": 1234,
"name": "MySpace",
"...": "..."
}

Update a space​

PATCH /api/spaces/:space_id
PATCH /api/projects/:project_id/spaces/:space_id

PUT works the same as PATCH.

parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe ID of a space, or its name when the project is specified
FieldRequiredNotes
namenoThe name of the space (not in a Connected Project)
descriptionnoThe description of the space
sandboxnoTrue for a sandbox space, false otherwise (not in a Connected Project)
min_run_periodnoPublication deadline for results in days (0 to disable)
result_set_aggregationnoTrue for a space that aggregates its results, false otherwise
stalenoAccepted only while the space is not stale
manualnoStandalone Projects only: true to enable Manual testing, false to disable it
publish_pathnoStandalone Projects only: where the space's Manual results are placed in the Suite tree

Fields a space can't change are ignored. As in Create a space, send manual inside a space object, or it is ignored.

Sample request:

PATCH /api/spaces/1234
Content-Type: application/json
{
"space": {
"name": "NewSpace",
"manual": true
}
}

A successful response returns no content:

205 Reset Content

Delete a space​

DELETE /api/spaces/:space_id
DELETE /api/projects/:project_id/spaces/:space_id

In a Connected Project, only a stale Space can be deleted (its branch or pull request is gone); otherwise the request returns 403.

parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe ID of a space, or its name when the project is specified

Sample request:

DELETE /api/spaces/1234

A successful response returns no content:

204 No Content

Results​

Each Space consists of a collection of Results. A Result is a collection of test cases organized in folders and Suites.

The counters are arrays of numbers, in this order:

CountersOrder
suite_counts[passed, failed, not applicable]
case_counts[passed, failed, not applicable, errored (blocked), untested]
annotation_counts[error, warn, info]
failure_counts[new, flaky, consistent, passing, resolved, exempt] (see Failure Tracking)
issue_counts[open, closed]

Each counter except annotation_counts, and duration, has a session_ twin: in a Space that aggregates its results, the plain one covers the whole Result and the session_ one only what ran in this Result, without what was carried from earlier ones (see Show). Elsewhere the two are the same.

FieldTypeNotes
idintegerThe unique ID of the result
namestringThe name of the result
sequence_numberintegerThe result's number in its space (1 for the first result)
descriptionstringThe description of the result
completebooleanTrue if the result is complete, false otherwise
pinnedbooleanTrue if the result is pinned, false otherwise
space_idintegerThe associated space
user_idintegerThe user who created the result
commit_idstringThe associated repo commit id (e.g. SHA for git)
build_urlstringThe URL of the originating CI build
build_statusstringThe status of the originating CI build: success, failure or error. Shown with the result, never used to judge Health (see CI Build Status and the CI Check)
build_started_attimestampWhen the originating CI build started
build_completed_attimestampWhen the originating CI build completed
suite_countsarrayThe contained suites counters
session_suite_countsarrayThe contained suites counters for session only results
case_countsarrayThe contained cases counters
session_case_countsarrayThe contained cases counters for session only results
annotation_countsarrayThe contained annotations counters
failure_countsarrayThe contained failures counters
session_failure_countsarrayThe contained failures counters for session only results
issue_countsarrayThe referenced issues counters
session_issue_countsarrayThe referenced issues counters for session only results
durationnumberThe duration of the result in milliseconds
session_durationnumberThe duration of the result in milliseconds for session only results
healthobjectThe health of the result
result_contents_urlstringThe URL of the Result contents API
result_failures_urlstringThe URL of the Result failures API
download_urlstringOnly with ?download=1 on Get a result: the URL to download the result as a Testspace XML file
created_attimestampThe date/time when the result was created
updated_attimestampThe date/time when the result was last updated

Health​

The health object holds the result's Health:

FieldTypeNotes
statestringsuccess (Healthy), failure (Unhealthy), invalid (Invalid), or pending while Testspace is still analyzing the result
partialbooleanTrue if the result is partial (a subset, or a metric not reported), false otherwise. Information beside the verdict: it doesn't change state
descriptionstringThe Health description, listing the checks that failed
badgesarrayThe result's badges: the test cases badge (named test) first, then each enabled metric badge

Each badge has:

FieldTypeNotes
metric_idintegerThe ID of the badge's metric
namestringThe badge's name, which its metric's settings can change (Release 78 renamed the coverage badges): match a badge by metric_id, not by name
valuenumber or stringThe badge's value for the result: the pass rate for test, the metric's badge value otherwise (not reported for a metric that normally reports and has no value in this result, hidden once its badge is hidden, see Metrics That Stop Reporting; blank when the metric has no data)
statusstringpassing (the check passed), failing (it failed), neutral (the badge has no criteria, so nothing is checked), no_results (no data for this result; not checked) or invalid (the test badge of an Invalid result)

To request details about results and to create or modify results use the following API methods.

List results​

GET /api/projects/:project_id/spaces/:space_id/results
GET /api/spaces/:space_id/results

Lists the Results that have content, newest first. A Result created with Create a result and never given content isn't listed; Get a result still returns it.

parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
nameOptional query parameter: lists only the results with this name
sequence_numberOptional query parameter: lists only the result with this number; -1 returns only the latest result (of that name, if name is given)

A successful response includes an array of results, newest first, as each entry in the list follows the same format as Get a result:

200 OK
Content-Type: application/json
[
{ "id": 1234, "name": "..." },
{ "id": 5678, "name": "..." },
]

Get a result​

This API point is provided only for the purpose of accessing a result record without its content. To obtain a result's content please use the Get result contents API or if interested in the associated result failures use the Get result failures API.

GET /api/projects/:project_id/spaces/:space_id/results/:result_id
GET /api/spaces/:space_id/results/:result_id
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name (the latest result of that name) or the ID of a result; 0 for the space's active result
downloadOptional query parameter: 1 adds download_url. The file is built in the background: until it is ready, downloading it returns 503 Service Unavailable with a Retry-After header

A successful response looks like:

200 OK
Content-Type: application/json
{
"id": 123456,
"name": "MyResult",
"sequence_number": 20,
"description": "Some description for my result",
"complete": true,
"pinned": false,
"user_id": 15,
"space_id": 1234,
"commit_id": "220cc4abf6989d38726403a085c542290c7f4c13",
"build_url": "https://...",
"build_status": "success",
"build_started_at": "2014-12-04T19:40:12Z",
"build_completed_at": "2014-12-04T19:58:30Z",
"suite_counts": [1508, 147, 4],
"session_suite_counts": [1508, 147, 4],
"case_counts": [35093, 517, 292, 5, 0],
"session_case_counts": [35093, 517, 292, 5, 0],
"annotation_counts": [5951, 3558, 332415],
"failure_counts": [5, 17, 495, 21, 8, 35],
"session_failure_counts": [5, 17, 495, 21, 8, 35],
"issue_counts": [2, 0],
"session_issue_counts": [2, 0],
"duration": 7201360.0,
"session_duration": 7201360.0,
"health": {
"state": "failure",
"partial": false,
"description": "Unhealthy. One or more Testspace metrics were out of range.\n* Test Cases: 522 unexpected failures! 98.5% passed (100.0% threshold and 35 exempt cases)",
"badges": [
{
"metric_id": 1234567,
"name": "test",
"value": 98,
"status": "failing"
},
{
"metric_id": 1234568,
"name": "line coverage",
"value": "85%",
"status": "passing"
}
]
},
"result_contents_url": "https://myorg.testspace.com/api/projects/12/spaces/1234/results/123456/contents",
"result_failures_url": "https://myorg.testspace.com/api/projects/12/spaces/1234/results/123456/failures",
"created_at": "2014-10-06T18:02:54Z",
"updated_at": "2014-12-04T19:59:42Z"
}

Create a result​

This API point is provided only for the purpose of creation of empty (no content) result records. To create a result and push content to it please use the Testspace client.

POST /api/projects/:project_id/spaces/:space_id/results
POST /api/spaces/:space_id/results
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
FieldRequiredNotes
namenoThe name of the result (Sequence_N if not given)
descriptionnoThe description of the result
completenoTrue for a complete result, false (default) for an incomplete one
commit_idnoThe associated repo commit id
build_urlnoThe URL of the originating CI build
build_statusnoThe status of the originating CI build: success, failure or error
build_started_atnoWhen the originating CI build started (ISO 8601)
build_completed_atnoWhen the originating CI build completed (ISO 8601)

Send at least one field: an empty body returns 400. When the Organization has reached its plan's Results limit, the request returns 423 Locked.

If the space has an incomplete result with the same name, no new result is created: the request updates that result instead, as Update a result does.

Sample request:

POST /api/spaces/1234/results
Content-Type: application/json
{
"name": "MyResult",
"description": "Some description for my result"
}

A successful response returns the new result following the same format as Get a result:

201 Created
Location: https://domain.testspace.com/api/spaces/1234/result_sets/123456
Content-Type: application/json
{
"id": 123456,
"name": "MyResult",
"...": "..."
}

Update a result​

This API point is provided only for the purpose of updating a result record without affecting its content. To update a result's content please use the Testspace client.

PATCH /api/projects/:project_id/spaces/:space_id/results/:result_id
PATCH /api/spaces/:space_id/results/:result_id

PUT and POST to the same URLs work the same as PATCH. Organization admins and the user who created the result can update it.

parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name or the ID of a result; 0 for the space's active result

Which fields are accepted depends on whether the result is complete; others are ignored:

FieldIncomplete resultComplete resultNotes
nameyesyesThe name of the result
descriptionyesyesThe description of the result
completeyesyesTrue to complete the result; false to reopen a complete result, which must be sent on its own
pinnednoyesTrue to pin the result, false to unpin it (see also Pin a result)
commit_idyesnoThe associated repo commit id
build_urlyesnoThe URL of the originating CI build
build_statusyesnoThe status of the originating CI build: success, failure or error
build_started_atyesnoWhen the originating CI build started (ISO 8601)
build_completed_atyesnoWhen the originating CI build completed (ISO 8601)

Sample request:

PATCH /api/spaces/1234/results/123456
Content-Type: application/json
{
"name": "NewResult",
"...": "..."
}

A successful response returns no content:

205 Reset Content

Pin a result​

A pinned result keeps its content when the retention policy removes older results' content. Only a complete result can be pinned or unpinned.

PUT /api/projects/:project_id/spaces/:space_id/results/:result_id/pin
PUT /api/spaces/:space_id/results/:result_id/pin

PATCH works the same as PUT.

parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name or the ID of a result; 0 for the space's active result

Sample request:

PUT /api/spaces/1234/results/123456/pin

A successful response returns no content:

205 Reset Content

Unpin a result​

DELETE /api/projects/:project_id/spaces/:space_id/results/:result_id/pin
DELETE /api/spaces/:space_id/results/:result_id/pin
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name or the ID of a result; 0 for the space's active result

Sample request:

DELETE /api/spaces/1234/results/123456/pin

A successful response returns no content:

204 No Content

Delete a result​

DELETE /api/projects/:project_id/spaces/:space_id/results/:result_id
DELETE /api/spaces/:space_id/results/:result_id

Only Organization admins and the user who published the Result can delete it.

parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name or the ID of a result

Sample request:

DELETE /api/spaces/1234/results/123456

The result is deleted in the background; the request returns at once. A successful response returns no content:

204 No Content

Get result contents​

Each Result is a collection of test cases organized in folders and Suites. Each folder and Suite has the counters described under Results.

Folder​

FieldTypeNotes
idintegerThe unique ID of the folder
result_idintegerThe associated result
typestringAlways folder
namestringThe name of the folder
pathstringThe full path to the folder
descriptionstringThe description of the folder
carriedbooleanTrue if the folder has one or more suites carried from another session, false otherwise
custom_dataobjectThe folder's custom data, by name
suite_countsarrayThe contained suites counters
session_suite_countsarrayThe contained suites counters for session only results
case_countsarrayThe contained cases counters
session_case_countsarrayThe contained cases counters for session only results
annotation_countsarrayThe contained annotations counters
failure_countsarrayThe contained failures counters
session_failure_countsarrayThe contained failures counters for session only results
issue_countsarrayThe referenced issues counters
session_issue_countsarrayThe referenced issues counters for session only results
durationnumberThe duration of the folder in milliseconds
session_durationnumberThe duration of the folder in milliseconds for session only results
folder_contents_urlstringThe URL of the folder's contents (by its ID, see below)

Suite​

FieldTypeNotes
idintegerThe unique ID of the suite
result_idintegerThe associated result
typestringsuite for a test suite; other kinds of suite are suite (<kind>), where <kind> is manual, exploratory, custom, code_coverage, static_analysis or code_change (e.g. suite (code_coverage))
namestringThe name of the suite
pathstringThe full path to the suite
descriptionstringThe description of the suite
statusstringThe status of the suite: passed, failed, missing or not applicable
carriedbooleanTrue if the suite is carried from another session, false otherwise
source_filestringThe source file reported for the suite, if any
runnerstringThe test runner reported for the suite, if any
start_timetimestampWhen the suite started, if reported
custom_dataobjectThe suite's custom data, by name
case_countsarrayThe contained cases counters
session_case_countsarrayThe contained cases counters for session only results
annotation_countsarrayThe contained annotations counters
failure_countsarrayThe contained failures counters
session_failure_countsarrayThe contained failures counters for session only results
issue_countsarrayThe referenced issues counters
session_issue_countsarrayThe referenced issues counters for session only results
durationnumberThe duration of the suite in milliseconds
session_durationnumberThe duration of the suite in milliseconds for session only results
suite_contents_urlstringThe URL of the Suite's contents API
download_urlstringThe URL to download from an XML-snippet of the contained test cases

Annotation​

FieldTypeNotes
idintegerThe unique ID of the annotation
result_idintegerThe associated result
typestringAlways annotation
namestringThe name of the annotation
descriptionstringThe description of the annotation
download_urlstringThe URL to download from the associated file content

To get the contents of a result use the following API methods.

GET /api/projects/:project_id/spaces/:space_id/results/:result_id/contents/<:path>
GET /api/spaces/:space_id/results/:result_id/contents/<:path>
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name or the ID of a result; 0 for the space's active result
:pathThe named folder/suite path; omit it for the result's top level

A folder or suite can also be given by its ID, as in folder_contents_url:

GET /api/projects/:project_id/spaces/:space_id/results/:result_id/contents/:element_id
GET /api/spaces/:space_id/results/:result_id/contents/:element_id

A successful response looks like:

  • a collection, when :path represents a Folder (or the top level)
200 OK
Content-Type: application/json
[
{
"id": 1234,
"result_id": 123456,
"type": "folder",
"name": "MyFolder",
"path": "path/MyFolder",
"description": "Some description for my folder",
"carried": false,
"suite_counts": [150, 14, 4],
"case_counts": [3509, 51, 29, 5, 0],
"annotation_counts": [5951, 355, 3324],
"failure_counts": [5, 17, 49, 21, 8, 35],
"issue_counts": [1, 0],
"duration": 1234.5,
"custom_data": {},
"folder_contents_url": "https://myorg.testspace.com/api/projects/12/spaces/1234/results/123456/contents/1234"
},
{
"id": 5678,
"result_id": 123456,
"type": "suite",
"name": "MySuite",
"path": "path/MySuite",
"description": "Some description for my suite",
"status": "failed",
"carried": false,
"source_file": "spec/my_suite_spec.rb",
"runner": null,
"start_time": "2014-12-04T19:42:10Z",
"case_counts": [50, 6, 2, 0, 0],
"annotation_counts": [10, 0, 3],
"failure_counts": [5, 17, 4, 2, 8, 5],
"issue_counts": [0, 0],
"duration": 1234.5,
"custom_data": {},
"suite_contents_url": "https://myorg.testspace.com/api/projects/12/spaces/1234/results/123456/suite_contents/5678",
"download_url": "https://..."
},
{
"id": 16369873,
"result_id": 123456,
"type": "annotation",
"name": "MyAnnotation",
"description": "Some description for my annotation",
"download_url": "https://..."
},
]

The session_ counters are left out of these examples.

  • an object, when :path represents a Suite
200 OK
Content-Type: application/json
{
"id": 5678,
"result_id": 123456,
"type": "suite",
"name": "MySuite",
"path": "path/MySuite",
"description": "Some description for my suite",
"status": "failed",
"case_counts": [50, 6, 2, 0, 0],
"annotation_counts": [10, 0, 3],
"failure_counts": [5, 17, 4, 2, 8, 5],
"duration": 1234.5,
"suite_contents_url": "https://myorg.testspace.com/api/projects/12/spaces/1234/results/123456/suite_contents/5678",
"download_url": "https://...",
"...": "..."
}

Get suite contents​

Each Suite is a collection of test cases. The list also includes tracked cases that didn't run in this result (status missing) and the suite's annotations (in the Annotation format).

FieldTypeNotes
idintegerThe unique ID of the test case
result_idintegerThe associated result
suite_idintegerThe associated suite
typestringAlways case
namestringThe name of the test case
descriptionstringThe description of the test case
statusstringThe status of the test case: passed, failed, errored (shown as blocked), not_applicable, untested, ignored or missing
causestringThe failure cause in case of failed/errored status
annotation_countsarrayThe contained annotations [error, warn, info] counters
durationnumberThe duration of the test case in milliseconds
trackingobjectA failure object if the test case is being tracked (without key and issues). For details see the Result failures API
issuesarrayThe keys of the issues the test case references (see Get result issues)

To get the contents of a suite use the following API methods.

GET /api/projects/:project_id/spaces/:space_id/results/:result_id/suite_contents/:suite_id
GET /api/spaces/:space_id/results/:result_id/suite_contents/:suite_id
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name or the ID of a result; 0 for the space's active result
:suite_idThe ID of a suite

A successful response looks like:

200 OK
Content-Type: application/json
[
{
"id": 456789,
"result_id": 123456,
"suite_id": 5678,
"type": "case",
"name": "MyCase",
"description": "blah blah",
"status": "failed",
"cause": "Expected 200, got 500",
"annotation_counts": [2, 0, 1],
"duration": 567.0,
"tracking": {
"state": "flaky",
"history": ["F", "P", "F2"],
"exempt": false,
"message": null,
"tracked_count": 4,
"failed_at": "2014-10-06T18:02:54Z",
"passed_at": null
},
"issues": []
}
]

Get result failures​

For each Result any failed/errored test case is being tracked. The set of those test cases is provided via the Failures end point.

FieldTypeNotes
keystringThe key of a test case failure (formatted as path/to/suite().case)
statestringThe tracking state of the failure: new, flaky, consistent, passing, resolved or retired. Failures shows only New, Flaky and Consistent; passing and resolved are the internal states described in Failure Tracking. retired (missing too long, tracking ended without a fix) appears in the result where tracking ended; like a resolved failure, it isn't listed in later results
historyarrayThe runs of the failure, oldest first (see History notation)
exemptbooleanTrue if the failure is exempt, false otherwise
messagestringThe triage note associated with the failure
issuesarrayThe keys of the issues linked to the failure
tracked_countintegerThe number of results the failure has been tracked for
failed_attimestampThe date/time when the failure first occurred
passed_attimestampThe date/time when the failure started passing before being resolved

History notation​

Each history entry is one run, or several identical runs in a row, written as [X|x][C]<status>[n]:

PartMeans
Ffailed
Eerrored (blocked)
Ppassed
Nnot applicable
Uuntested
Mmissing: the test didn't run in that result (counts toward retiring it)
Dmissing from a subset or an Invalid result (doesn't count toward retiring it)
X prefixexempt, set in Triage
x prefixexempt as an expected failure: a pytest xfail, or a test case pushed with the exempt attribute
Cthe run was carried from an earlier session (in a Space that aggregates its results)
n suffixthe number of identical runs in a row, e.g. P4

To get the failures of a result use the following API methods.

GET /api/projects/:project_id/spaces/:space_id/results/:result_id/failures
GET /api/spaces/:space_id/results/:result_id/failures
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name or the ID of a result; 0 for the space's active result

A successful response looks like:

200 OK
Content-Type: application/json
[
{
"key": "path/to/MySuite().MyCase",
"state": "flaky",
"history": ["F", "P3", "F"],
"exempt": false,
"message": null,
"tracked_count": 8,
"failed_at": "2014-10-06T18:02:54Z",
"passed_at": null,
"issues": []
},
{
"key": "path/to/MySuite().OtherCase",
"state": "passing",
"history": ["F3", "P4"],
"exempt": false,
"message": "Fixed by the timeout change",
"tracked_count": 7,
"failed_at": "2014-10-01T10:15:31Z",
"passed_at": "2014-10-03T08:20:12Z",
"issues": ["#482"]
}
]

Get result issues​

The issues referenced by the result's test cases, for example through Triage (see the Issues tab).

FieldTypeNotes
keystringThe issue's key, e.g. #482 or PROJ-123
titlestringThe issue's title
urlstringThe issue's URL in its issues provider
statestringopen or closed
case_countsarrayThe referencing cases [passed, failed, not applicable, errored (blocked), untested] counters; exempt cases count as not applicable

To get the issues of a result use the following API methods.

GET /api/projects/:project_id/spaces/:space_id/results/:result_id/issues
GET /api/spaces/:space_id/results/:result_id/issues
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:result_idThe name or the ID of a result; 0 for the space's active result

A successful response looks like:

200 OK
Content-Type: application/json
[
{
"key": "#482",
"title": "Search times out on large projects",
"url": "https://github.com/myorg/myrepo/issues/482",
"state": "open",
"case_counts": [0, 1, 0, 0, 0]
}
]

Metrics​

For each Result push to a Space a set of Metrics are collected. A Metric consists of a collection of historical datasets.

FieldTypeNotes
idintegerThe unique ID of the metric
namestringThe name of the metric
data_sourcestringThe path to the data source of the metric
chart_typestringThe type (i.e. lines or columns) of the metric's chart
max_rangeintegerThe "default" max range on the metric's chart y-axes
max_range_limitintegerThe max range "limit" (0 for unlimited) on the metric's chart y-axes
unitsstringThe units of the data being graphed
space_idintegerThe associated space
badge_urlstringThe URL of the associated badge
embed_urlstringThe URL of the associated graph
variablesarrayThe "variables" (calculated of the input dataset) being graphed
thresholdsarrayThe "thresholds" (calculated of the input dataset) being graphed
badgeobjectThe "badge" (calculated of the variables/thresholds and/or input datasets) being computed
created_attimestampThe date/time when the metric was created
updated_attimestampThe date/time when the metric was last updated

To request details about metrics and to create or modify metrics use the following API methods.

List metrics​

GET /api/projects/:project_id/spaces/:space_id/metrics
GET /api/spaces/:space_id/metrics
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
nameOptional query parameter: lists only the metrics with this name

A successful response includes an array of metrics, ordered by name, as each entry in the list follows the same format as Get a metric:

200 OK
Content-Type: application/json
[
{ "id": 1234, "name": "..." },
{ "id": 5678, "name": "..." },
]

Get a metric​

This API point is provided only for the purpose of accessing a metric record without its datasets. To obtain metric's datasets please use the Get Metric Datasets API.

GET /api/projects/:project_id/spaces/:space_id/metrics/:metric_id
GET /api/spaces/:space_id/metrics/:metric_id
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:metric_idThe ID of a metric

A successful response looks like:

200 OK
Content-Type: application/json
{
"id": 123456,
"name": "MyMetric",
"data_source": "/path/to/suite[dataset_label]",
"chart_type": "lines",
"max_range": 10,
"max_range_limit": 10,
"units": "seconds",
"space_id": 1234,
"badge_url": "https://...",
"embed_url": "https://...",
"variables": [
{
"name": "var-one",
"color": "#008000",
"expression": "round(d1/1000,1)"
},
],
"thresholds": [
{
"name": "thresh-one",
"color": "#464646",
"expression": "3"
},
],
"badge": {
"name": "thresh-one",
"value_expression": "concat(v1,'s')",
"criteria_expression": "v1 <= t1",
"is_enabled": true
},
"created_at": "2014-10-06T18:02:54Z",
"updated_at": "2014-12-04T19:59:42Z"
}

Create a metric​

Only Custom Metrics can be created via this API.

POST /api/projects/:project_id/spaces/:space_id/metrics
POST /api/spaces/:space_id/metrics
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
FieldRequiredNotes
nameyesThe name of the metric
data_sourceyesThe path to the data source of the metric
chart_typenoThe type (i.e. lines or columns) of the metric's chart
max_rangenoThe "default" max range on the metric's chart y-axes
max_range_limitnoThe max range "limit" (0 for unlimited) on the metric's chart y-axes
unitsnoThe units of the data being graphed
variablesyesThe "variables" (calculated of the input dataset) being graphed
thresholdsnoThe "thresholds" (calculated of the input dataset) being graphed
badgenoThe "badge" (calculated of the variables/thresholds and/or input datasets) being computed

Sample request:

POST /api/spaces/1234/metrics
Content-Type: application/json
{
"name": "MyMetric",
"data_source": "/path/to/suite[dataset_label]",
"...": "..."
}

A successful response returns the new metric following the same format as Get a metric:

201 Created
Location: https://domain.testspace.com/api/spaces/1234/metrics/123456
Content-Type: application/json
{
"id": 123456,
"name": "MyMetric",
"...": "..."
}

Update a metric​

PATCH /api/projects/:project_id/spaces/:space_id/metrics/:metric_id
PATCH /api/spaces/:space_id/metrics/:metric_id

The Test Suites, Code Change, Health and Failure Tracks metrics can't be updated (403).

PUT works the same as PATCH.

parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:metric_idThe ID of a metric
FieldRequiredNotes
namenoThe name of the metric
data_sourcenoThe path to the data source of the metric
chart_typenoThe type (i.e. lines or columns) of the metric's chart
max_rangenoThe "default" max range on the metric's chart y-axes
max_range_limitnoThe max range "limit" (0 for unlimited) on the metric's chart y-axes
unitsnoThe units of the data being graphed
variablesnoThe "variables" (calculated of the input dataset) being graphed
thresholdsnoThe "thresholds" (calculated of the input dataset) being graphed
badgenoThe "badge" (calculated of the variables/thresholds and/or input datasets) being computed

Sample request:

PATCH /api/spaces/1234/metrics/123456
Content-Type: application/json
{
"name": "NewMetric"
}

A successful response returns no content:

205 Reset Content

Delete a metric​

DELETE /api/projects/:project_id/spaces/:space_id/metrics/:metric_id
DELETE /api/spaces/:space_id/metrics/:metric_id

The standard metrics (Test Suites, Test Cases, Health, Failure Tracks) can't be deleted (403). parameter | description ------| ----------- :project_id | The name or the ID of the associated project | :space_id | The name (only when project is specified) or the ID of the associated space | :metric_id | The ID of a metric |

Sample request:

DELETE /api/spaces/1234/metrics/123456

A successful response returns no content:

204 No Content

Get metric datasets​

A Metric consists of a collection of historical datasets, one per result that reported the metric.

FieldTypeNotes
idintegerThe unique ID of the dataset
metric_idintegerThe associated metric
result_set_idintegerThe associated result
raw_valuesobjectThe set of raw metric data (named d1 to d10) pushed with the result
evaluated_valuesobjectThe set of evaluated data (named v1..v5, t1, t2, b and bc) that are being graphed
created_attimestampThe date/time when the metric dataset was created
updated_attimestampThe date/time when the metric dataset was last updated
published_attimestampThe date/time of the associated result, where the dataset is placed on the metric's graph

To get the datasets of a metric use the following API methods.

GET /api/projects/:project_id/spaces/:space_id/metrics/:metric_id/datasets
GET /api/spaces/:space_id/metrics/:metric_id/datasets
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of the associated space
:metric_idThe ID of a metric
daysOptional query parameter: how many days back to list datasets for (default: 28)

A successful response, newest first, looks like:

200 OK
Content-Type: application/json
[
{
"id": 369040,
"metric_id": 94828,
"result_set_id": 112168,
"raw_values": {"d1":2093,"d2":1900,"d3":2740,"d4":null,"d5":null,"d6":null,"d7":null,"d8":null,"d9":null,"d10":null},
"evaluated_values": {"v1":"2.1","v2":"1.9","v3":"2.7","v4":null,"v5":null,"t1":3,"t2":null,"b":"2.1s","bc":true},
"created_at":"2019-10-11T10:58:02.000-07:00",
"updated_at":"2019-10-11T10:58:02.000-07:00",
"published_at":"2019-10-11T10:58:02.000-07:00"
},
]

Insights​

Insights summarize a project's or a space's results over a period. The values are formatted as Insights shows them: most are a percentage followed by the numbers it is computed from, e.g. "92.7% (873/942)", and N/A when there isn't enough data. Invalid results are left out of the statistics.

Get project insights​

GET /api/projects/:project_id/insights
parameterdescription
:project_idThe name or the ID of a project
daysOptional query parameter: the period in days (default: 28)

The response has one object for each of the three indicators: results_strength, test_effectiveness and workflow_efficiency. Each has a status (good, mediocre, poor or unknown) and a status_message explaining it, followed by the indicator's statistics (see Project Insights). The key regressed_spaces is regressed_branches in a Connected Project.

A successful response looks like:

200 OK
Content-Type: application/json
{
"results_strength": {
"status": "good",
"status_message": "Pass Rate is greater than 95%.",
"pass_rate": "95.6% (2,112/2,210)",
"health_rate": "9.8% (5/51)",
"health_recovery_time": "3.0d",
"invalid_rate": "0% (0/51)",
"file_churn": "N/A",
"pass_rate_change": "N/A ",
"health_rate_change": "N/A ",
"health_recovery_rate": "100% (1/1)",
"failure_volatility": 0.05,
"unhealthy_metrics": 2,
"flaky_failures": "22.7% (0.5/2.2)",
"error_failures": "9.1% (0.2/2.2)",
"invalid_with_errors": 0
},
"test_effectiveness": {
"status": "mediocre",
"status_message": "Effective Regression is over 30%. Most likely caused by system instability.",
"effective_regression": "33.3% (17/51)",
"new_failures": 21,
"test_cases": 44,
"test_duration": 46672.0,
"regressed_spaces": "80% (4/5)",
"unique_regressions": "38.6% (17/44)",
"new_failure_rate": "33.3% (1.2/3.6)",
"test_suites": 6
},
"workflow_efficiency": {
"status": "poor",
"status_message": "Resolved Failures are below 60%.",
"resolved_failures": "33.3% (7/21)",
"failure_resolution_time": "0.0d",
"long_term_failures": "50% (1/2)",
"merged_pull_requests": "N/A ",
"pr_resolution_time": "N/A",
"failures_per_regression": "5.1% (2.2/43)",
"triage_long_term_failures": "33.3% (0.3/0.9)",
"new_prs": 0,
"closed_prs": 0,
"rejected_prs": 0,
"stale_prs": 0,
"pr_comments": 0,
"pr_additions": 0,
"pr_deletions": 0,
"pr_changed_files": 0,
"pr_participants": 0
}
}

Get space insights​

GET /api/projects/:project_id/spaces/:space_id/insights
GET /api/spaces/:space_id/insights
parameterdescription
:project_idThe name or the ID of the associated project
:space_idThe name (only when project is specified) or the ID of a space
daysOptional query parameter: the period in days (default: 28)

The response is one object (see Space Cards): the number of results in the period, the growth of test cases and static analysis issues, a <metric name>_growth key for each code coverage metric, then the space's Results Strength, Test Effectiveness and Workflow Efficiency statistics, without the indicator statuses. In a Connected Project it also has merged_prs and pr_resolution_time.

A successful response looks like:

200 OK
Content-Type: application/json
{
"results": 20,
"test_growth": "0 | 0.0%",
"line coverage_growth": "1.2%",
"static_analysis_growth": "0%",
"pass_rate": "92.7% (873/942)",
"health_rate": "0% (0/20)",
"invalid_rate": "0% (0/20)",
"file_churn": "N/A",
"pass_rate_change": "N/A ",
"health_rate_change": "N/A ",
"health_recovery_rate": "0% (0/1)",
"failure_volatility": 0.29,
"unhealthy_metrics": 0,
"test_cases_processed": 984,
"flaky_failures": "28.6% (1.0/3.5)",
"error_failures": "14.3% (0.5/3.5)",
"invalid_with_errors": 0,
"unique_regressions": "60% (12/20)",
"new_failures": 16,
"new_failure_rate": "28.3% (1.3/4.6)",
"test_cases": 49,
"test_suites": 7,
"test_duration": 51208.0,
"resolved_failures": "31.3% (5/16)",
"failure_resolution_time": "0.0d",
"failures_per_regression": "7.4% (3.5/47)",
"long_term_failures": "25% (1/4)",
"triage_long_term_failures": "46.2% (0.6/1.3)"
}