# Testpad API

Welcome to the reference manual for the Testpad API.

This manual assumes you know what Testpad is, how the user interface works, and most importantly, what everything is called.

<br>

---
**Initial Access**
<br>
<br>

Please note, for now:

- the API feature has to be enabled, by Testpad Support, to be able to access it at all  
- only account “owner” users can configure API access (i.e. issue access tokens)

<br>

---
**An Evolving API**
<br>
<br>

The API is brand new for Testpad and will be updated in response to feedback from customers.

Please see the [Change Log](/openapi/change-log) for information on what might have changed since you last looked.

Please also see the [Unsupported Capabilities](/openapi/unsupported-capabilities) section for some discussion of what can't be done yet. 

And if you have a scenario or use-case in mind for the API that is not yet supported, please email support@testpad.com.

<br>

---
**Mostly RESTful**
<br>
<br>

The API mostly conforms to RESTful principles.

- HTTP **GET** requests are used to retrieve information.  
- HTTP **POST** requests are used for actions like creating new folders, scripts, tests and test runs, where the server will generally be inventing new IDs for these objects and returning them in the response payload.  
- HTTP **PATCH** requests are used for modifying parts of existing objects, supplying new (replacement) values for a subset of the keys of those objects.  
- Testpad does not currently support HTTP **PUT** requests – the wholesale replacement of objects with a new object.  
- Testpad does not currently support HTTP **DELETE** requests – these are likely to be supported in the future, but we are protecting you and ourselves from accidental data loss for the time being.

To do something with Testpad's API, you need to send a request to one of the API endpoints. These are the URL path that the request is being directed to, and should be thought of as sending a message to the relevant 'owning' object.

For example, a GET request to `/projects/` is to fetch data on all projects.  

Or, a POST request to `/projects/:p/folders` is a create action on that project’s collection of folders, i.e. to create a new folder in the list of folders.

---

## API Server

<br>

**HTTPS only**
<br>
<br>

The API only responds to requests sent securely using HTTPS.

Clients must validate SSL/TLS certificates (including the certificate chain and hostname) to ensure they are communicating with Testpad. Failure to properly validate the certificate exposes your integration to man-in-the-middle attacks, where malicious actors could intercept, modify, or steal your data.

<br>

---
**Domain**
<br>
<br>

Find the API Server at `https://api.testpad.com`.

Note the subdomain is `api` and not your account ID.

<br>

---
**Paths**
<br>
<br>

All API endpoints are hosted on paths that begin with the common prefix `/api/v1/`.  

At some point in the future, if backwards incompatible changes are introduced, these will be introduced at a new version number, e.g. `/api/v2/`.  

However, in general, every attempt will be made to keep changes and new features backwards compatible, and while this holds true, the API will continue to be hosted at `/api/v1/`.




Version: 1.0

## Servers

```
https://api.testpad.com/api/v1
```

## Download OpenAPI description

[Testpad API](https://api-docs.testpad.com/_bundle/openapi.yaml)

## Authentication

All requests to the Testpad API must include the Authorization HTTP Header that supplies an API access token for your account.

<br>

**HTTP Header**
<br>
<br>


The `Authorization` header value must have the format: `Authorization: apikey <TOKEN>`

The token must be preceded by the prefix `apikey` to be considered a valid authorization value. It is envisaged that alternative authorization schemes may be added in the future, and these would be differentiated with a different prefix.

<br>

**API Access Token**
<br>
<br>

Create and manage API Access Tokens on the API settings page in the Testpad app (account Owners only).

The API settings page is found in the Settings section of the navigation links in the bottom left of the main project view.

If you cannot see a link to API settings (and you are an account Owner), then your account probably has not yet been enabled for API access – please contact support@testpad.com to request access.

<br>

**Enabling API access**

API access is off by default. Two things must both be true for any request to succeed:

1. Your account must have the API feature switched on by Testpad. Until then, every request returns `403 Forbidden` with `{"error": "The API is not available for this account."}` — contact support@testpad.com to request access.
2. An account Owner must turn API Access on for the account (on the API settings page). While it is off, every request returns `403 Forbidden` with `{"error": "API access is turned off for this account."}`.

A request with a missing, malformed, expired, deleted or disabled token returns `401 Unauthorized` instead.

Security notes:

- Tokens are 64-character case-sensitive strings of letters and digits (a-z, A-Z, 0-9).  
- Tokens are generated by Testpad using a cryptographically-strong random number generator.
- An account may generate and make use of multiple tokens, e.g. to give different teams different tokens.
- For now, the API is secured with tokens that grant access to all API capabilities and across all projects. It is expected that more fine-grained control such as role-specific and project-specific access keys will be supported in the future.


### Identify the caller

 - [GET /whoami](https://api-docs.testpad.com/openapi/authentication/paths/~1whoami/get.md): Returns the account and API key associated with the supplied token. Useful as a connectivity and authentication check.

## ◉ Project Endpoints

### Get all projects

 - [GET /projects](https://api-docs.testpad.com/openapi/project-endpoints/paths/~1projects/get.md): Retrieves a list of all active projects visible to the authenticating API key. Only basic information (name, id, description) is returned per project.

Archived projects are not included.

Look to these endpoints for retrieving information about the folder and script contents of projects:

- GET /projects/:p/folders
- GET /projects/:p/folders/:f

### Get a project

 - [GET /projects/{project_id}](https://api-docs.testpad.com/openapi/project-endpoints/paths/~1projects~1%7Bproject_id%7D/get.md): Retrieves the basic information about the project specified by project_id.
Project IDs can be found in the app by inspecting the URL or via the API endpoint to Get all projects.

Does not retrieve the script and folder contents of a project.

For project contents, please see:
- GET /projects/:p/folders – for getting all the script and folder contents of a project
- GET /projects/:p/folders/:f – for getting the contents of a particular folder in a project

## ◉ Folder Endpoints

### Get all folders

 - [GET /projects/{project_id}/folders](https://api-docs.testpad.com/openapi/folder-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders/get.md): Retrieves the complete content tree of folders and scripts contained by the project, project_id.

By default, the returned tree of folders and scripts consists only of their names and IDs. Folder and script objects can be expanded with more details, such as progress statistics, test details and test runs details by using URL parameters as defined below.

For large projects, it is recommended to use the more specific endpoint Get a folder GET /projects/:p/folders/:f to retrieve the contents of just one folder rather than all folders in the project.

Takes Common URL Parameters for controlling the contents of contained objects.

Defaults for common parameters:
- subfolders=all
- scripts=terse
- tests=none
- fields=none
- runs=none
- results=none
- progress=none

### Create a folder

 - [POST /projects/{project_id}/folders](https://api-docs.testpad.com/openapi/folder-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders/post.md): Creates a new folder at the top level of the project project_id.

The new folder is supplied as a JSON object in the request body supplying only the name of the new folder.

Note: it is not possible to create a new folder together with a new script (or sub-folder) in the same request.
Instead, a first request must be made to create a new folder, and then subsequent requests can be used to populate it with content.

### Get a folder

 - [GET /projects/{project_id}/folders/{folder_id}](https://api-docs.testpad.com/openapi/folder-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders~1%7Bfolder_id%7D/get.md): Retrieves the basic information and contents of the folder specified by folder_id.

Folder IDs are strings that start with an 'f' followed by an integer. To find a folder ID in the app, click on a folder to open it and inspect the URL.

By default, the returned tree of folders and scripts consists only of their names and IDs. Folder and script objects can be expanded with more details, such as progress statistics, test details and test runs details by using URL parameters as defined below.

In particular, note that the subfolders URL parameter can be used to limit the response to just the folder requested, without also returning the contents of nested sub-folders.

Takes Common URL Parameters for controlling the contents of contained objects.

Defaults for common parameters:
- subfolders=all
- scripts=terse
- tests=none
- fields=none
- runs=none
- results=none
- progress=none

### Modify a folder

 - [PATCH /projects/{project_id}/folders/{folder_id}](https://api-docs.testpad.com/openapi/folder-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders~1%7Bfolder_id%7D/patch.md): Modifies the name of the folder folder_id in the project project_id.

To modify the contents of a folder, please see:
- Create a sub-folder POST /projects/:p/folders/:f/folders – for creating a new folder within a folder
- Create a script in a folder POST /projects/:p/folders/:f/scripts – for creating a script within a folder

### POST data
name string — The new name of the folder.

### Returns
JSON response payload containing:

folder object — Summary of the modified folder.  
context object — Project and folderPath context.

### Defaults for common parameters
(no common parameters are used).

### Create a sub-folder

 - [POST /projects/{project_id}/folders/{folder_id}/folders](https://api-docs.testpad.com/openapi/folder-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders~1%7Bfolder_id%7D~1folders/post.md): Creates a new sub-folder of the folder folder_id within the project project_id.

The new folder is supplied as a JSON object in the request body supplying only the name of the new folder.

Note, it is not possible to create a new folder and new script (or sub-folder) contents in the same request. Instead, a first request must be made to create a new folder, and then subsequent requests can be used to populate it with content.

## ◉ Script Endpoints

### Create a script in a project

 - [POST /projects/{project_id}/scripts](https://api-docs.testpad.com/openapi/script-endpoints/paths/~1projects~1%7Bproject_id%7D~1scripts/post.md): Creates a new script in the top level of the project project_id.

If you want to create a script within a particular folder, please refer to Create a script in a folder POST /projects/:p/folders/:f/script, a nearly identical endpoint but for the specifying which folder to put the script in.

### Create a script in a folder

 - [POST /projects/{project_id}/folders/{folder_id}/scripts](https://api-docs.testpad.com/openapi/script-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders~1%7Bfolder_id%7D~1scripts/post.md): Creates a new script in the folder folder_id within the project project_id.

The new script is supplied as a JSON object in the request body and can contain tests,
runs, run headers, results and custom fields.

### URL Parameters
insert enum or integer  
Controls where the script will be created within the specified folder.

first (default) — the script is placed at the top of the folder.  
last — the script is placed at the end of the folder.  
as integer, N — the script is placed after the Nth item in the folder.

### POST data
name string — The name of the new script.  
description string (OPTIONAL) — The description for the new script.  
comments string (OPTIONAL) — The report comments for the new script.

tests — See Supplying Test Text.  
fields — Order/visibility/definition of run header fields.  
runs — List of test run objects as defined in Supplying Test Runs.

### Returns
JSON response payload containing:

script object — Summary of the new script.  
context object — Project and folderPath context.

### Defaults for common parameters
(no common parameters are used).

### Get a script

 - [GET /scripts/{script_id}](https://api-docs.testpad.com/openapi/script-endpoints/paths/~1scripts~1%7Bscript_id%7D/get.md): Retrieves information about the script specified by the script ID, script_id.

Script IDs are integers and are unique across projects. To find the ID of a script via the app, browse to the relevant script and inspect the page URL.

By default, most information about the script is returned, including its tests, fields, run headers and results. Use the common URL Parameters to modify the contents of the response object.

Takes Common URL Parameters for controlling the contents of contained objects.

Defaults for common parameters:
- subfolders (not relevant)
- scripts=full
- tests=full
- fields=full
- runs=full
- results=full
- progress=terse

### Modify a script

 - [PATCH /scripts/{script_id}](https://api-docs.testpad.com/openapi/script-endpoints/paths/~1scripts~1%7Bscript_id%7D/patch.md): Modifies the metadata of the script script_id. Supply any of the following
fields to replace their current values:

- name string — the script's name (title).
- description string — the script's description.
- comments string — the report comments for the script.

Only metadata is changed here. To add tests, see Add tests to a script
POST /scripts/:s/tests. To add results, add a test run
POST /scripts/:s/runs.

### Defaults for common parameters
(no common parameters are used).

### Get a script's tests

 - [GET /scripts/{script_id}/tests](https://api-docs.testpad.com/openapi/script-endpoints/paths/~1scripts~1%7Bscript_id%7D~1tests/get.md): Returns the flat list of tests (test rows) in the script script_id, each with
its indent showing where it sits in the outline.

For the tests formatted as strings or a single block of text, use the script
endpoint GET /scripts/:s with the tests URL parameter instead.

### Add tests to a script

 - [POST /scripts/{script_id}/tests](https://api-docs.testpad.com/openapi/script-endpoints/paths/~1scripts~1%7Bscript_id%7D~1tests/post.md): Appends one or more tests to the end of the script script_id (or at a chosen
position with the insert parameter).

Tests can be supplied in the same forms as when creating a script (see
Supplying Test Text):

1. As JSON (Content-Type: application/json) — either:
   - a list of test objects. Each object takes text (required), and optionally
     tags (a comma or space separated string), notes, and indent (an integer
     outline depth). You may supply your own id on every test in the list, or on
     none of them; or
   - a list of strings, one test per string, with leading tabs for indentation.
2. As plain text (Content-Type: text/plain) — a single string with one test
   per line, using leading tabs for indentation, exactly as the app's export
   produces. This is the same format the tests=text response returns.

Results cannot be attached when adding tests. A test row has no run to hold a
result, so any results field in a test object is ignored (and is not reflected
back in the response). To record results, create the script with runs
(POST /projects/:p/scripts) or add a run (POST /scripts/:s/runs).

### Defaults for common parameters
(no common parameters are used).

### Get a single test

 - [GET /scripts/{script_id}/tests/{test_id}](https://api-docs.testpad.com/openapi/script-endpoints/paths/~1scripts~1%7Bscript_id%7D~1tests~1%7Btest_id%7D/get.md): Returns one test (test row) from the script script_id.

## ◉ Run Endpoints

### Add a test run

 - [POST /scripts/{script_id}/runs](https://api-docs.testpad.com/openapi/run-endpoints/paths/~1scripts~1%7Bscript_id%7D~1runs/post.md): Adds a test run to the script script_id.

The test run will be appended to the set of test runs already present.

Both headers and results are optional, so you can add an empty run,
a run with only headers, or a run with results.

To record a retest of an existing run rather than a fresh run, pass the
retest query parameter (see below).

This endpoint cannot be used to create new header fields that have not already been defined for the script.
Any unrecognized header fields will be ignored.

### POST data
The test run is defined by supplying a test run object as defined in Supplying Test Runs.

### Including Results
To include results with the test run, the test run object can include the results field, which has the choice of format defined in Supplying Test Results.

### Returns
JSON response payload containing:

run object — A summary of test run that was created, including its new id field.

### Defaults for common parameters
(no common parameters are used).

### Get a test run

 - [GET /scripts/{script_id}/runs/{run_id}](https://api-docs.testpad.com/openapi/run-endpoints/paths/~1scripts~1%7Bscript_id%7D~1runs~1%7Brun_id%7D/get.md): Returns a single test run from the script script_id, including its headers and
its results.

## ◉ Note Endpoints

### Get a list of notes at the top-level of a project

 - [GET /projects/{project_id}/notes](https://api-docs.testpad.com/openapi/note-endpoints/paths/~1projects~1%7Bproject_id%7D~1notes/get.md): Fetches any notes (note items) that sit at the top level of the project.

For notes in specific folders, see GET /projects/:p/folders/:f/notes.

For more description of notes and their representation, see POST /projects/:p/notes.

### Create a note in a project

 - [POST /projects/{project_id}/notes](https://api-docs.testpad.com/openapi/note-endpoints/paths/~1projects~1%7Bproject_id%7D~1notes/post.md): Creates a new note in the top level of the project project_id.

Notes are text comments displayed beside scripts and folders in the project view,
allowing for additional notes, comments or instructions to be displayed at the
project/folder and folder report levels.

The new note is supplied as a JSON object in the request body with the
contents of the note in the name field. This might seem like an odd
choice of field name, but is used for consistency with the other types of items
found in projects and folders, namely Folders, Scripts and Notes.
All project/folder items have a name field, which is the text displayed in the
project/folder view. As such, the contents of a Note are in fact its displayed "name".

### Get the list of notes in a folder

 - [GET /projects/{project_id}/folders/{folder_id}/notes](https://api-docs.testpad.com/openapi/note-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders~1%7Bfolder_id%7D~1notes/get.md): Fetches the list of notes within a folder (but not its subfolders).

For notes in the root folder of a project, see GET /projects/:p/notes.

For more description of notes and their representation, see POST /projects/:p/notes.

### Create a note in a folder

 - [POST /projects/{project_id}/folders/{folder_id}/notes](https://api-docs.testpad.com/openapi/note-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders~1%7Bfolder_id%7D~1notes/post.md): Creates a new note in the folder folder_id within the project project_id.

For more description of notes and their representation, see POST /projects/:p/notes.

### Get a note

 - [GET /projects/{project_id}/notes/{note_id}](https://api-docs.testpad.com/openapi/note-endpoints/paths/~1projects~1%7Bproject_id%7D~1notes~1%7Bnote_id%7D/get.md): Returns the project/folder note specified by note_id.

For more description of notes and their representation, see POST /projects/:p/notes.

### Modify a note

 - [PATCH /projects/{project_id}/notes/{note_id}](https://api-docs.testpad.com/openapi/note-endpoints/paths/~1projects~1%7Bproject_id%7D~1notes~1%7Bnote_id%7D/patch.md): Modifies the project/folder Note specified by note_id.

The specified note is modified by simply supplying replacement text
contents in the name field of the payload JSON object.

For more description of notes and their representation, see POST /projects/:p/notes.

### Get a note in a folder

 - [GET /projects/{project_id}/folders/{folder_id}/notes/{note_id}](https://api-docs.testpad.com/openapi/note-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders~1%7Bfolder_id%7D~1notes~1%7Bnote_id%7D/get.md): Returns the note note_id that sits in folder folder_id.

For more description of notes and their representation, see POST /projects/:p/notes.

### Modify a note in a folder

 - [PATCH /projects/{project_id}/folders/{folder_id}/notes/{note_id}](https://api-docs.testpad.com/openapi/note-endpoints/paths/~1projects~1%7Bproject_id%7D~1folders~1%7Bfolder_id%7D~1notes~1%7Bnote_id%7D/patch.md): Modifies the note note_id in folder folder_id by supplying replacement text
in the name field.

For more description of notes and their representation, see POST /projects/:p/notes.

## Webhook Events

A topic names what happened, in `entity.action` form. Your webhook's filter decides which of these it receives, and each event carries its topic in `_event.topic`. Switch on that.

Subscribe with an exact topic (`result.fail`), a whole family (`result.*`), or everything (`*`):

| Filter | Matches |
|---|---|
| `*` | Every event. |
| `result.*` | Any result event. |
| `run.*` | Any run event. |
| `user.*` | Any user event. |

<br>

---
**Result topics**
<br>
<br>

Sent as test results are set, changed, or cleared. When one action sets several results at once, each outcome arrives as a single event whose `results` array holds every test of that outcome, so a bulk fill is a few events, not hundreds.

| Topic | Sent when |
|---|---|
| `result.pass` | A test was marked pass. |
| `result.fail` | A test was marked fail. |
| `result.block` | A test was marked blocked. |
| `result.query` | A test was marked query. |
| `result.skip` | A test was excluded from the run. |
| `result.clear` | A test's result was cleared. |

<br>

---
**Run topics**
<br>
<br>

| Topic | Sent when |
|---|---|
| `run.started` | A run got its first result and moved to started. |
| `run.completed` | A run was completed. |
| `run.reopened` | A completed run was reopened. |
| `run.assigned` | A run's assignee changed, including being unassigned. |
| `run.cleared` | Every result in a run was cleared at once. |

<br>

---
**User topics**
<br>
<br>

| Topic | Sent when |
|---|---|
| `user.invited` | Someone was invited to the account. |
| `user.joined` | An invited person verified their email and joined. |
| `user.removed` | A member was removed from the account. |
| `user.role_changed` | A member's role was changed. |

<br>

---
**Ping**
<br>
<br>

| Topic | Sent when |
|---|---|
| `ping` | You pressed ping on the webhooks settings page. Sent to that one webhook only, whatever its filter. |

<br>

---
**Who caused it**
<br>
<br>

Every event names the actor in `context.actor`. A team member shows their real name and email. Work done by Testpad Support on your behalf shows as "Testpad Support", and anything done through the API shows as "API". Support and API actions carry no email. Events never include details of any other account.

<br>

---
**What you won't get**
<br>
<br>

Copying a script, retesting, moving content between projects, and account-to-account migration are all silent. They re-home existing data rather than re-running it, so they don't fire result or run events. Seeding the example project on a new account is silent too.


### result.pass

 - [POST result.pass](https://api-docs.testpad.com/openapi/webhook-events/webhookresultpass.md): A test was marked pass.

### result.fail

 - [POST result.fail](https://api-docs.testpad.com/openapi/webhook-events/webhookresultfail.md): A test was marked fail.

### result.block

 - [POST result.block](https://api-docs.testpad.com/openapi/webhook-events/webhookresultblock.md): A test was marked blocked.

### result.query

 - [POST result.query](https://api-docs.testpad.com/openapi/webhook-events/webhookresultquery.md): A test was marked query.

### result.skip

 - [POST result.skip](https://api-docs.testpad.com/openapi/webhook-events/webhookresultskip.md): A test was excluded from the run.

### result.clear

 - [POST result.clear](https://api-docs.testpad.com/openapi/webhook-events/webhookresultclear.md): A test's result was cleared.

### run.started

 - [POST run.started](https://api-docs.testpad.com/openapi/webhook-events/webhookrunstarted.md): A run got its first result and moved to started.

### run.completed

 - [POST run.completed](https://api-docs.testpad.com/openapi/webhook-events/webhookruncompleted.md): A run was completed.

### run.reopened

 - [POST run.reopened](https://api-docs.testpad.com/openapi/webhook-events/webhookrunreopened.md): A completed run was reopened.

### run.assigned

 - [POST run.assigned](https://api-docs.testpad.com/openapi/webhook-events/webhookrunassigned.md): A run's assignee changed, including being unassigned.

### run.cleared

 - [POST run.cleared](https://api-docs.testpad.com/openapi/webhook-events/webhookruncleared.md): Every result in a run was cleared at once.

### user.invited

 - [POST user.invited](https://api-docs.testpad.com/openapi/webhook-events/webhookuserinvited.md): Someone was invited to the account.

### user.joined

 - [POST user.joined](https://api-docs.testpad.com/openapi/webhook-events/webhookuserjoined.md): An invited person verified their email and joined.

### user.removed

 - [POST user.removed](https://api-docs.testpad.com/openapi/webhook-events/webhookuserremoved.md): A member was removed from the account.

### user.role_changed

 - [POST user.role_changed](https://api-docs.testpad.com/openapi/webhook-events/webhookuserrolechanged.md): A member's role was changed.

### ping

 - [POST ping](https://api-docs.testpad.com/openapi/webhook-events/webhookping.md): A manual test event sent from the webhooks settings page to one webhook.

