openapi: 3.0.3
info:
  title: Testpad API
  version: '1.0'
  description: >+
    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/`.


servers:
  - url: https://api.testpad.com/api/v1
tags:
  - name: Authentication
    description: >
      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 Owner-type user),
      then your account probably has not yet been enabled for API access –
      please contact support@testpad.com to request access.


      Security notes:


      - Tokens are 3072-bit random numbers encoded as a 48-character
      case-sensitive string.  

      - 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.
  - name: ◉ Project Endpoints
  - name: ◉ Folder Endpoints
  - name: ◉ Script Endpoints
  - name: ◉ Run Endpoints
  - name: ◉ Note Endpoints
  - name: Common URL Parameters
    description: >+
      <br>


      Multiple endpoints are available for retrieving folders and scripts, and
      their responses can contain substantial amounts of data. To help clients
      request only the information they need, these endpoints support a common
      set of URL parameters.


      If not supplied in requests, default values for these parameters will be
      assumed. Note that the defaults used vary depending on whether the request
      is for a single script object or a folder of several script objects.


      <br>


      ---

      **subfolders** *(enum)*

      <br>


      Controls whether the nested contents of a retrieved folder should also be
      retrieved.  

      Only applicable to endpoints retrieving folder items.


      - `none` – the contents of any subfolders in the target folder are not
      included

      - `all` - *(default)* – the contents, and recursively nested contents, of
      a retrieved folder are included


      <br>


      ---

      **scripts** *(enum)*

      <br>


      Controls how much of the script meta data to include (e.g., description,
      report comments, creation date).


      - `terse` *(default for folder endpoints)* – only includes the script’s
      name and ID  

      - `full` *(default for script endpoints)* – adds all the basic information
      about the script, including description, creation date, report comments,
      and whether the script is archived.


      This parameter does **not** affect inclusion of tests, fields, runs, or
      results.


      <br>


      ---

      **tests** *(enum)*

      <br>


      Controls whether or not (and in which format) the tests of a script are
      included in the `tests` field of script objects.


      - `none` *(default for folder endpoints)* – excludes the `tests` field
      entirely  

      - `full` *(default for script endpoints)* – includes tests as a list of
      objects with fields: `id`, `indent`, `text`, and `tags`  

      - `list` – includes tests as a list of strings, with leading whitespace to
      show indentation  

      - `text` – includes tests as a single string, with each test separated by
      newlines and indentation preserved


      <br>


      ---

      **testswith** *(list of enum)*

      <br>


      Modifies how tests are returned when `tests` are included.

      Most useful when formatting tests as lists or long strings.


      Combine multiple values with commas (e.g., `testswith=hashtags,ids`).


      - `none` *(default)* – test text is included as is, without decoration

      - `hashtags` – includes tags as Twitter-style hashtags appended to each
      test text string. If tests are being returned as objects, the `tags` field
      is omitted.

      - `ids` – prefixes each test text string with the test ID. Ignored if
      tests are objects.  

      - `_ids` – same as `ids`, but right-aligns ID numbers (4 digits wide).
      Ignored if tests are objects.


      <br>


      ---

      **fields** *(enum)*

      <br>


      Controls the contents of the `fields` field of script objects.


      This field defines the set of headers available for each run header (e.g.,
      run number, tag filters, custom fields etc).


      - `none` *(default for folder endpoints)* – field information is not
      returned  

      - `full` *(default for script endpoints)* – fields are defined as a list
      of objects with:  
        - `id`  
        - `label`  
        - `shown` (boolean)  
      - `list` – fields are returned as a simple list of all labels in use  

      - `list_shown` – same as `list`, but only includes fields marked as
      *shown*


      <br>


      ---

      **runs** *(enum)*

      <br>


      Controls how test run data is included in the `runs` field of script
      objects.


      - `none` *(default for folder endpoints)* – data on the test runs are not
      included

      - `full` *(default for script endpoints)* – script objects will contain
      full run definitions, including state, tester, and header values, but not
      results (which depend on the `results` parameter below)

      - `terse` – returns a brief summary of each test run (one-line string
      label summarizing header values and run number)  


      <br>


      ---

      **retests** *(enum)*

      <br>


      Controls whether to include old (superseded) test runs.


      - **`latest`** *(default)* – only the latest retest of each run is
      returned  

      - **`all`** – includes all test run data, including superseded runs


      <br>


      ---

      **results** *(enum)*

      <br>


      Controls whether results data is included in the response (but only if the
      `runs` field is being included).


      Results are included as the `results` field inside run objects (nested in
      `runs`).


      - `none` *(default for folder endpoints)* – the `results` field is
      excluded from run objects

      - `full` *(default for script endpoints)* – results are included as a list
      of result objects, with fields:  
        - `result` *(e.g., `pass`, `fail`, `query`, `blocked`)*  
        - `comments` - string
        - `issues` - string

      Only non-empty result objects are included.


      <br>


      ---

      **progress** *(enum)*

      <br>

                  "total": 4,
                  "pass": 1,
                  "fail": 3,
                  "block": 0,
                  "query": 0,

      Controls how progress statistics are included in the `progress` field of
      folders, scripts, and runs.


      - `none` *(default for folder endpoints)* – `progress` fields are excluded

      - `terse` *(default for script endpoints)* – `progress` fields are
      included and contain:
        - `total` - integer - the number of tests that have a result value recorded, i.e. the total tried so far
        - `pass` - integer - the count of results marked as pass
        - `fail` - integer - the count of results marked as fail
        - `block` - integer - the count of results marked as blocked
        - `query` - integer - the count of results marked as queried
        - `summary`: a human-readable summary string of these counts
      - `full` – returns progress as an object with individual count fields as
      well as percentage values. The percentage values are rounded to the
      nearest integer, set to be at least 1% if >0, and adjusted to all sum to
      100% (thus making them useful for e.g. CSS %width values in a dashboard
      display).


      <br>

  - name: Supplying Test Text
    description: >-
      Test text can be provided as part of creating new scripts via these
      endpoints:


      - `POST /projects/:p/scripts` — create a script in a project  

      - `POST /projects/:p/folders/:f/scripts` — create a script in a folder


      **Choice of format**:


      - As a **string**: a block of text with a test per line  

      - As a **list of strings**: a test per item in the list  

      - As a **list of objects**: a test per item in the list, with fields such
      as `id`, `text`, `indent`, `tags`, `notes`, `results`


      Key details:


      - When supplying tests as a string or list of strings, **IDs cannot be
      specified**.  

      - Indentation can be inferred from leading whitespace (when `indent` is
      not supplied).  

      - Tags can be supplied using hashtags at the end of the test.  

      - Multiline cells are supported in **list of strings** (via `\n`), but
      **not** supported when supplying tests as a single string.  

      - Results can be supplied per-test when using the **list of objects**
      format.
  - name: Supplying Test Runs
    description: >
      Test runs (columns) can be created using several endpoints:


      - `POST /projects/:p/scripts` — create a script in a project, including
      one or more test runs  

      - `POST /projects/:p/folders/:f/scripts` — create a script in a folder,
      including one or more test runs  

      - `POST /scripts/:s/runs` — add a single test run to a script


      Where multiple test runs are being supplied (the create new script
      endpoints), the `runs` field will be a list of the run objects.  

      Where a single test run is being supplied (the add a single test run
      endpoint), the payload is a single test run object.


      **Test Run object** (fields):


      - `id` (optional)  

      - `headers` (optional)  

      - `completed` (boolean or `"auto"`) (optional)  

      - `results` (object) (optional)


      Notes:


      - The ID can only be supplied when **creating scripts**. Once a script
      exists, new IDs will be created for you by Testpad.  

      - Built-in header fields are read-only (`_run`, `_createdDate`,
      `_createdTime`).  

      - Any header fields that do not receive a value will be left empty.  

      - Any header field values supplied in the test run that do not exist in
      the script will be ignored.
  - name: Supplying Test Results
    description: >-
      Test results can be provided to Testpad as part of creating Scripts using
      these endpoints:


      - `POST /projects/:p/scripts`  

      - `POST /projects/:p/folders/:f/scripts`


      Results can be provided either **together with a test row** (per row),
      **together with a test run column** (per column), or **individually**.


      **Per-row (in test objects)**:

      - `results` as a **list** maps in order to the defined test runs.  

      - `results` as an **object** uses test run IDs as keys.


      **Per-column (in run objects)**:

      - `results` is an **object** with test IDs as keys.


      **Individual result formats**:

      - **String**: `"pass"`, `"fail"`, `"blocked"`, `"exclude"`, `"query"`  

      - **List**: `[result, comment, issue]` (triple)  

      - **Object**: `{ "result": "...", "comment": "...", "issue": "..." }`
  - name: Progress Objects
    description: >+

      Test result statistics for test runs, scripts, folders and folders of
      folders, are represented as **progress objects**.


      - **Terse**: `pass`, `fail`, `blocked`, `query`, `total`, `summary`  

      - **Full**: adds percentages (`passPc`, `failPc`, etc.), `tried`,
      `remain`, and `counts`


      The percentages are rounded to the nearest integer, adjusted to be at
      least 1 when non-zero, and such that they always sum to 100.

  - name: Error Handling
    description: >
      During development of client code (code that makes requests to the Testpad
      API), it is recommended to catch all errors and to print their details out
      to the console or a log file for inspection of what went wrong.


      Once in production, client code might scale back on the verbosity of its
      error reporting, however, it should nevertheless always maintain specific
      handling for the following error conditions, which, in theory, could
      happen to any request:


      <br>


      `401 Unauthorized`


      The error 401 Unauthorized will be returned if your access token does not
      have, or no longer has, the relevant permissions to access the API.


      <br>


      `429 Too Many Requests`


      The error 429 Too Many Requests will be returned to any request that
      exceeds Testpad's rate limits. Please see [Rate
      Limiting](//openapi/rate-limiting) for details.


      If your code receives this error, it must wait for the indicated amount of
      time before trying again.
  - name: Rate Limiting
    description: >
      <br>


      The API protects itself from excessive load by limiting the rate at which
      received requests will be processed.


      There are several types of rate limit applied, and requests must 'pass'
      all of these to be successful. I.e. if any one of these different rate
      limiters is triggered, then the request will be rejected.


      <br>


      **Custom Limits**


      The default rate limits are defined below and are subject to change. For
      now, all subscription plans have the same limits, but this may well change
      in the future, with the larger plans obviously allowing for higher API
      usage requirements.


      If you are finding your rate limits insufficient, please contact
      support@testpad.com to discuss what you are trying to do and the
      possibility of increasing these limits for your account.


      <br>


      ---

      **Rejected Requests**

      <br>

      <br>


      Requests rejected for exceeding a rate limit will get a `429 TOO MANY
      REQUESTS` response.


      The response will contain the `Retry-After` HTTP header, specifying how
      many seconds until a repeat attempt will be successful.


      <br>


      ---

      **Global (Load Balancer) Rate Limits**

      <br>

      <br>


      Testpad deploys two types of rate limiter, a global rate limiter that
      applies to all requests, along with several request-specific limiters that
      apply different rates for different types of request.


      The global rate limit is **1000 requests per hour**, which is an average
      of **1 request every 3 seconds**, but allows for bursts of up to **100
      requests at a time**.


      If 100 requests arrived back to back, then the client would have to wait
      300 seconds before being able to continue (i.e. maintaining the average
      rate of 1000 requests per hour).


      <br>


      ---

      **GET (Fetch) Rate Limits**

      <br>

      <br>


      For GET (fetch) requests, the API applies two rate limits:


      - **1GB** of response data per day, and  

      - a burst rate limit of **50MB every 3 minutes**


      Within any 3 minute period, Testpad will not respond if more

      than 50MB of data have already been returned.


      And within any 24 hour period, Testpad will not respond if more than 1GB
      of data has already been returned.


      <br>


      ---

      **POST (Write) Rate Limits**

      <br>

      <br>


      For POST (write) requests, the API applies limits to how many scripts

      and how many test runs can be created:


      - **500 new scripts per month**, and  

      - a burst limit of **100 scripts per hour**
        
        <br>

      - **1000 new test runs per month**, and  

      - a burst limit of **200 test runs per hour**


      <br>


      ---

      **How the Rate Limits work**

      <br>

      <br>


      > Note – the following HTTP headers are not implemented yet,

      > but we keep their documentation here as they help explain how the rate

      > limiters are implemented.


      Every API response contains rate limit status information as HTTP headers.


      `X-Testpad-Rate-Limit-Read` — Present in responses to GET requests that
      are attempting to retrieve (read) information.  


      `X-Testpad-Rate-Limit-Write` — Present in responses to POST requests that
      are attempting to create information.


      <br>

      The value of these fields is a list of rate limiter names and their
      current statistics.


      <br>

      Examples:


      `fetch_daily[85.2% 893387 of 1048576 KB/day]` — describing the rate
      limiter called 'fetch_daily' which has a current capacity of 893387 KB
      (how much more data it will allow through), out of a maximum capacity of
      1048576 KB (1 GB) per day.


      `scripts_monthly[99.0% 493 of 500 scripts/month]` — describing the rate
      limited called 'scripts_monthly' which has a current capacity of 493
      scripts (how many new scripts it will permit), out of a maximum capacity
      for 500 new scripts per month.


      <br>

      Rate limiters will reject requests once its current capacity value goes
      below zero.


      <br>

      The current capacity of each rate limiter is continuously recharging. The
      value of `Retry-After` is the number of seconds until the capacity level
      of a rate limiter will go back above zero.


      This means that clients do not have to wait e.g. a whole month before they
      can continue after a 429 error. Instead, they only need to wait until the
      capacity of the relevant rate limiter has recharged to a positive value
      again. However, do note that if a request is made immediately after a
      limiter's capacity has just returned positive, then that capacity is
      likely to immediately become negative again and thus block subsequent
      requests.
  - name: Change Log
    description: |-
      **[1.0.0] – 2025-11-01**

      General release of the Testpad API.


      **[0.9.0] - 2025-08-01**

      Pre-release for early adopter beta-testing.
  - name: Unsupported Capabilities
    description: >
      There are many possibilities for the future of Testpad's API. Here is a
      (obviously non-exhaustive) list of notable features that might be expected
      of the API but which are **not supported for the time being**.


      - **Creating and Modifying Projects**  

      Projects cannot be created by the API and basic project information like
      names and descriptions cannot be modified. However, the contents of
      project (scripts and folders) can be modified via the several project and
      folder endpoints.


      - **Folder manipulations**  

      Folder items (scripts, notes and nested folders) cannot be moved around.
      There's no support for moving folder items between folders or between
      projects.  

      Similarly, there's no support yet for archiving or unarchiving scripts,
      notes and folders.


      - **Script field set modifications**  

      The set of fields in a script cannot be modified by the API. Custom fields
      can be created as part of the creation of a new script, but once created,
      the API cannot modify the set of fields defined for a script.


      - **Adding tests to scripts**  

      For now, the set of tests in a script can only be created at the time the
      script is created.


      - **Deleting content**  

      For now, there is no provision for deleting content with the API. This is
      partly because most use-cases for the API will be about creating content
      to record new testing, but also to protect new API users from themselves
      until good safeguards against accidental delete operations have been
      devised. Suggestions welcome!
  - name: Support
    description: >-
      For support, or if you have a scenario or use-case in mind for the API
      that is not yet supported, please email **support@testpad.com**.
paths:
  /projects:
    get:
      summary: Get all projects
      description: >-
        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` 
      tags:
        - ◉ Project Endpoints
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X GET "https://api.testpad.com/api/v1/projects" \
                 -H "Authorization: apikey $ACCESS_TOKEN"
      responses:
        '200':
          description: Successful response, containing the list of projects
          content:
            application/json:
              examples:
                default:
                  summary: Simple list of projects found
                  value:
                    projects:
                      - id: 59
                        name: Example Project
                        description: An example project for API queries
                        created: '2024-05-12T11:09:52.758000+00:00'
                      - id: 80
                        name: Another Project
                        description: Another example project for API querying
                        created: '2024-03-12T12:06:20.253000+00:00'
  /projects/{project_id}:
    get:
      summary: Get a project
      description: >-
        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
      tags:
        - ◉ Project Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          description: The project ID.
          schema:
            type: integer
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X GET "https://api.testpad.com/api/v1/projects/14" \
                 -H "Authorization: apikey $ACCESS_TOKEN"
      responses:
        '200':
          description: >
            JSON response object of the project object, containing the following
            fields:  


            - `id` integer — The ID of the project.  

            - `name` string — The name (title) of the project.  

            - `description` string — The project description, which in the app,
            is only displayed in the project settings page for a project.  

            - `created` timestamp string — The timestamp for when the project
            was created.
          content:
            application/json:
              examples:
                default:
                  summary: Fetch a single project at /projects/14
                  value:
                    project:
                      id: 72
                      name: Example Project 14
                      description: The 14th example project for demonstrating API queries
                      created: '2017-09-14T15:41:04.222000+00:00'
  /projects/{project_id}/folders:
    get:
      summary: Get all folders
      description: >-
        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](/openapi/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
      tags:
        - ◉ Folder Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          description: The project ID.
          schema:
            type: integer
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X GET "https://api.testpad.com/api/v1/projects/119/folders" \
                 -H "Authorization: apikey $ACCESS_TOKEN"
      responses:
        '200':
          description: >
            JSON response payload containing:


            - `folders` - the list of items in the requested folder, consisting
            of script objects, note objects or further (sub) folder objects.


            All items contain the common fields:  

            - `type` - enum — The type of item that this object is representing,
            one of script, note or folder.

            - `id` - integer or string — The ID of the item. Script IDs are
            integers. Folder IDs are strings that start with an 'f'. Note IDs
            are strings that start with an 'n'.  

            - `name` - string — The name (title) of the script, note or folder.


            Folder items will also contain the field:

            - `contents` - list of object — The items contained in the
            sub-folder (recursively).


            Script and Folder items may contain progress statistics depending on
            the `progress` URL parameter:

            - `progress` - object — The progress object for the script or
            folder, in either full or terse form depending on the progress URL
            parameter.


            Script items may contain any of the usual script object fields,
            again depending on the URL parameters (`tests`, `fields`, `runs` and
            `results`).
          content:
            application/json:
              examples:
                default:
                  summary: |
                    Example: GET /projects/119/folders
                  value:
                    folders:
                      - type: script
                        id: 23013
                        name: An example script A
                      - type: script
                        id: 23012
                        name: An example script B
                      - type: folder
                        id: f34
                        name: new folder
                        contents:
                          - type: script
                            id: 23018
                            name: A nested script C
                          - type: script
                            id: 23017
                            name: A nested script D
                    context:
                      folderPath:
                        folders: []
                        path: /
                      project:
                        id: 72
                        name: An example project
                        description: New project
                        created: '2017-09-14T15:41:04.222000+00:00'
                progressTerse:
                  summary: |
                    Example: GET /projects/119/folders?progress=terse
                  value:
                    folders:
                      - type: script
                        id: 23013
                        name: An example script A
                        progress:
                          summary: Pass:15 Fail:4 Blocked:0 Query:0 Total:19/24 (79%)
                      - type: script
                        id: 23012
                        name: An example script B
                        progress:
                          summary: Pass:4 Fail:1 Blocked:0 Query:0 Total:5/15 (33%)
                      - type: folder
                        id: f34
                        name: new folder
                        progress:
                          summary: Pass:24 Fail:0 Blocked:0 Query:1 Total:25/30 (83%)
                        contents:
                          - type: script
                            id: 23018
                            name: A nested script C
                            progress:
                              summary: >-
                                Pass:24 Fail:0 Blocked:0 Query:1 Total:25/30
                                (83%)
                          - type: script
                            id: 23017
                            name: A nested script D
                            progress:
                              summary: Pass:0 Fail:0 Blocked:0 Query:0 Total:0/0 (0%)
                    context:
                      folderPath:
                        folders: []
                        path: /
                      project:
                        id: 72
                        name: An example project
                        description: New project
                        created: '2017-09-14T15:41:04.222000+00:00'
    post:
      summary: Create a folder
      description: >-
        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.
      tags:
        - ◉ Folder Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          description: The project ID.
          schema:
            type: integer
        - name: insert
          in: query
          required: false
          schema:
            type: string
          description: >
            Controls where the folder will be created within the top-level items


            `first` (default) — the folder is placed at the top of the
            project.  

            `last` — the folder is placed at the end of the project's
            contents.  

            `N` - integer — the folder is placed after the Nth item in the
            project.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: The name of the new folder
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X POST "https://api.testpad.com/api/v1/projects/119/folders"
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "name": "My new folder"
            }
            EOF
      responses:
        '200':
          description: |
            JSON response payload containing:

            - `folder` - object — A summary of the new folder.  
            - `context` - object — Project and folderPath context.
          content:
            application/json:
              examples:
                default:
                  summary: |
                    Example: POST /projects/119/folders
                  value:
                    folder:
                      id: f10
                      name: My new folder
                      contents: []
                    context:
                      project:
                        id: 119
                        name: ApiProj2
                        description: New project
                        created: '2020-12-01T11:24:33.360000+00:00'
                      folderPath:
                        folders: []
                        path: /
  /projects/{project_id}/folders/{folder_id}:
    get:
      summary: Get a folder
      description: >-
        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](/openapi/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
      tags:
        - ◉ Folder Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          description: The project ID.
          schema:
            type: integer
        - name: folder_id
          in: path
          required: true
          description: The folder ID.
          schema:
            type: string
      x-codeSamples:
        - lang: bash
          label: curl
          source: >
            curl -X GET "https://api.testpad.com/api/v1/projects/119/folders/f1"
            \
                 -H "Authorization: apikey $ACCESS_TOKEN"
      responses:
        '200':
          description: >
            JSON response containing


            `folder` - object, containing:


            - `id` - string — The ID of the retrieved folder

            - `name` - string — The name (title) of the folder

            - `type` - "folder" — Always the string 'folder' 

            - `progress` - object (OPTIONAL) — If included by the progress URL
            parameter

            - `contents` - list of objects — Items contained in the retrieved
            folder
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/folders/f1
                  value:
                    folder:
                      type: folder
                      id: f1
                      name: An example Folder
                      contents:
                        - type: script
                          id: 23022
                          name: An example script C
                        - type: script
                          id: 23023
                          name: An example script D
                    context:
                      folderPath:
                        folders: []
                        path: /
                      project:
                        id: 119
                        name: ApiProj2
                        description: New project
                        created: '2020-12-01T11:24:33.360000+00:00'
    patch:
      summary: Modify a folder
      description: >-
        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).
      tags:
        - ◉ Folder Endpoints
      parameters:
        - $ref: '#/components/parameters/AuthorizationHeader'
        - name: project_id
          in: path
          required: true
          description: The project ID.
          schema:
            type: integer
        - name: folder_id
          in: path
          required: true
          description: The folder ID.
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: The name of the new folder
            examples:
              default:
                summary: /projects/119/folders/f11
                value:
                  name: My modified folder name
      x-codeSamples:
        - lang: bash
          label: curl
          source: >
            curl -X PATCH
            "https://api.testpad.com/api/v1/projects/119/folders/f11"
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "name": "My modified folder name"
            }

            EOF
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/folders/f11
                  value:
                    folder:
                      id: f11
                      name: My modified folder name
                      contents: []
                    context:
                      project:
                        id: 119
                        name: ApiProj2
                        description: New project
                        created: '2020-12-01T11:24:33.360000+00:00'
                      folderPath:
                        folders:
                          - id: f1
                            name: An example parent folder
                        path: An example parent folder/
  /projects/{project_id}/folders/{folder_id}/folders:
    post:
      summary: Create a sub-folder
      description: >-
        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.
      tags:
        - ◉ Folder Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          description: The project ID.
          schema:
            type: integer
        - name: folder_id
          in: path
          required: true
          description: The folder ID.
          schema:
            type: string
        - name: insert
          in: query
          required: false
          schema:
            type: string
            description: >
              Controls where the folder will be created within the parent
              folder.


              `first` (default) — the folder is placed at the top of the parent
              folder.  

              `last` — the folder is placed at the end of the parent folder.  

              `N' - integer — the folder is placed after the Nth item in the
              parent folder.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: The name of the new folder
            examples:
              default:
                summary: /projects/119/folders/f1/folders
                value:
                  name: My new folder
      x-codeSamples:
        - lang: bash
          label: curl
          source: >
            curl -X POST
            "https://api.testpad.com/api/v1/projects/119/folders/f1/folders"
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "name": "My new sub-folder"
            }

            EOF
      responses:
        '200':
          description: |
            JSON response payload containing:

            - `folder` - object — A summary of the new folder
            - `context` - object — Project and folderPath context
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/folders/f1/folders
                  value:
                    folder:
                      id: f12
                      name: My new sub-folder
                      contents: []
                    context:
                      project:
                        id: 119
                        name: ApiProj2
                        description: New project
                        created: '2020-12-01T11:24:33.360000+00:00'
                      folderPath:
                        folders:
                          - id: f1
                            name: An example parent folder
                        path: An example parent folder/
  /projects/{project_id}/scripts:
    post:
      summary: Create a script in a project
      description: >-
        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. 
      tags:
        - ◉ Script Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          schema:
            type: integer
          description: The project ID.
        - name: insert
          in: query
          required: false
          schema:
            type: string
          description: >
            Controls where the script will be created within the project:


            `first` (default) — the folder is placed at the top of the parent
            folder.  

            `last` — the folder is placed at the end of the parent folder.  

            `N` - integer — the folder is placed after the Nth item in the
            parent folder.
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ScriptInput'
            examples:
              minimal:
                summary: Minimal (defaults only)
                value: {}
              named:
                summary: Named script with a couple of tests
                value:
                  name: Regression Suite
                  tests:
                    - login works
                    - logout works
              full:
                summary: With fields, tests, runs and results
                value:
                  name: API smoke
                  description: Core endpoints
                  fields:
                    - browser
                    - (component)
                    - id: platform
                      show: false
                  tests:
                    - text: GET /health is 200
                      tags: HIGH
                    - text: GET /version returns semver
                  runs:
                    - headers:
                        build: 1.1.0
                        browser: Chrome
                      results:
                        '1': pass
                        '2': pass
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X POST "https://api.testpad.com/api/v1/projects/119/scripts"
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "name": "a new script",
              "fields": ["(weather)", "build", "date"],
              "runs": [
                { "id": 1, "headers": { "build": "1.1.0", "weather": "fair" }, "results": { "2": "pass", "7": "blocked" } },
                { "id": 2, "headers": { "build": "1.1.0", "weather": "poor" }, "results": { "2": { "result": "blocked", "comment": "cigars not" } } }
              ],
              "tests": [
                { "text": "API-supplied test line one", "tags": "HIGH", "results": { "1": "pass", "2": "pass" } },
                { "text": "line two", "results": { "1": "pass", "2": { "result": "fail", "comments": "no cigar" } } },
                { "text": "line three", "results": { "1": "pass", "2": "pass" } }
              ]
            }
            EOF
      responses:
        '200':
          description: |
            JSON response containing the script object just created:

            - `script`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Script'
              examples:
                default:
                  summary: /projects/119/scripts
                  value:
                    script:
                      id: 8
                      name: scripted script 10
                      created: '2025-04-29T15:35:50.516'
                      description: ''
                      archived: false
                      fields:
                        - ...
                      tests:
                        - id: 1
                          indent: 0
                          text: test line A
                          tags: HELLO
                        - id: 2
                          indent: 1
                          text: test line B
                        - id: 3
                          indent: 1
                          text: test line C
                        - id: 4
                          indent: 1
                          text: test line D
                        - id: 5
                          indent: 0
                          text: test line E
                      progress:
                        total: 8
                        pass: 3
                        fail: 2
                        block: 0
                        query: 1
                        summary: Pass:3 Fail:2 Block:0 Query:1 Total:6/8
                      type: script
                    context:
                      project:
                        id: 119
                        name: Example Project
                        description: Am example project
                        created: '2025-04-25T13:28:25.852'
                      folderPath:
                        folders:
                          - id: f1
                            name: Release 0.1
                        path: Release 0.1/
  /projects/{project_id}/folders/{folder_id}/scripts:
    post:
      summary: Create a script in a folder
      description: >-
        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).
      tags:
        - ◉ Script Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          schema:
            type: integer
          description: The project ID.
        - name: folder_id
          in: path
          required: true
          schema:
            type: string
          description: The folder ID.
        - name: insert
          in: query
          required: false
          schema:
            type: string
          description: >
            Controls where the script will be created within the target folder:


            `first` (default) — the script is placed at the top of the folder.  

            `last` — the script is placed at the end of the folder's contents.  

            `N` - integer — the script is placed after the Nth item in the
            folder.
      requestBody:
        required: true
        content:
          application/json:
            examples:
              default:
                summary: /projects/119/folders/f1/scripts
                value: |
                  {
                    "name": "scripted script 10",
                    "description": "created by script",
                    "fields": ["(weather)", "build", "date"],
                    "runs": [
                      { "headers": { "build": "1.1.0", "weather": "fair", "new": "surprise" }, "results": { "5": "query", "7": "blocked" } },
                      { "headers": { "build": "1.1.0", "weather": "poor", "new": "!" } }
                    ],
                    "tests": [
                      { "text": "test line A", "tags": "HELLo", "notes": "" },
                      { "text": "test line B", "indent": 1, "notes": "", "results": { "1": "pass", "2": "fail" } },
                      { "indent": 1, "text": " test line C", "results": [ "pass", "fail" ] },
                      { "indent": 1, "text": " test line D", "results": [ { "result": "pass", "issue": "TPT-123" }, { "issue": "TPT-124" } ] },
                      { "text": "test line E" }
                    ]
                  }
      x-codeSamples:
        - lang: bash
          label: curl
          source: >
            curl -X POST
            "https://api.testpad.com/api/v1/projects/119/folders/f1/scripts"
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "name": "scripted script 10",
              "description": "created by script",
              "fields": ["(weather)", "build", "date"],
              "runs": [
                { "headers": { "build": "1.1.0", "weather": "fair", "new": "surprise" }, "results": { "5": "query", "7": "blocked" } },
                { "headers": { "build": "1.1.0", "weather": "poor", "new": "!" } }
              ],
              "tests": [
                { "text": "test line A", "tags": "HELLo", "notes": "" },
                { "text": "test line B", "indent": 1, "notes": "", "results": { "1": "pass", "2": "fail" } },
                { "indent": 1, "text": " test line C", "results": [ "pass", "fail" ] },
                { "indent": 1, "text": " test line D", "results": [ { "result": "pass", "issue": "TPT-123" }, { "issue": "TPT-124" } ] },
                { "text": "test line E" }
              ]
            }

            EOF
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/folders/f1/scripts
                  value: |
                    {
                      "script": {
                        "id": 8,
                        "name": "scripted script 10",
                        "created": "2025-04-29T15:35:50.516",
                        "description": "",
                        "archived": false,
                        "fields": [ "..." ],
                        "tests": [
                          { "id": 1, "indent": 0, "text": "test line A", "tags": "HELLO" },
                          { "id": 2, "indent": 1, "text": "test line B" },
                          { "id": 3, "indent": 1, "text": "test line C" },
                          { "id": 4, "indent": 1, "text": "test line D" },
                          { "id": 5, "indent": 0, "text": "test line E" }
                        ],
                        "progress": { "total": 8, "pass": 3, "fail": 2, "block": 0, "query": 1, "summary": "Pass:3 Fail:2 Block:0 Query:1 Total:6/8" },
                        "type": "script"
                      },
                      "context": {
                        "project": { "id": 119, "name": "Example Project", "description": "Am example project", "created": "2025-04-25T13:28:25.852" },
                        "folderPath": { "folders": [ { "id": "f1", "name": "Release 0.1" } ], "path": "Release 0.1/" }
                      }
                    }
  /scripts/{script_id}:
    get:
      summary: Get a script
      description: >-
        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](/openapi/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
      tags:
        - ◉ Script Endpoints
      parameters:
        - name: script_id
          in: path
          required: true
          description: The script ID.
          schema:
            type: integer
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X GET "https://api.testpad.com/api/v1/scripts/23"
                 -H "Authorization: apikey $ACCESS_TOKEN"
      responses:
        '200':
          description: >
            JSON response containing:

            `script` - object, containing:


            - `id` - string — The ID of the retrieved script

            - `name` - string — The name (title) of the script

            - `progress` - object — The progress statistics for all the test
            runs in the script

            - `comments` - string - Comment text to be included in reports for
            this script

            - `created` - timestamp - the date/time this script was created

            - `archived` - boolean - whether or not this script has been
            archived within its project

            - `fields` - array of field objects - the list of header fields this
            script uses for test runs

            - `tests` - the list of tests in this script, with the format
            depending on the `tests` URL parameter

            - `runs` - the list of test runs in this script
          content:
            application/json:
              examples:
                default:
                  summary: /scripts/23
                  value: |
                    {
                      "script": {
                        "id": 23,
                        "name": "Hello World",
                        "description": "An example script to fetch from the API",
                        "comments": "Comments to be included in the report for this script",
                        "created": "2020-10-22T13:48:58.123000+00:00",
                        "archived": false,
                        "fields": [
                          { "id": "_run", "label": "number", "show": true },
                          { "id": "_tester", "label": "tester", "show": true },
                          { "id": "_createdDate", "label": "date", "show": true },
                          { "id": "_createdTime", "label": "time", "show": false },
                          { "id": "_tags", "label": "tag filter", "show": false },
                          { "id": "browser", "label": "Browser", "show": true }
                        ],
                        "tests": [
                          { "id": 1, "indent": 0, "text": "A first title row" },
                          { "id": 2, "indent": 1, "text": "child of first row", "tags": "HIGH" }
                          { "id": 3, "indent": 1, "text": "child two of first row" },
                          { "id": 4, "indent": 1, "text": "child three of first row" },
                          { "id": 5, "indent": 1, "text": "child four of first row" },
                        ]
                        "runs": [
                          {
                            "id": "1",
                            "created": "2025-06-03T14:28:15.466",
                            "state": "complete",
                            "label": "1 / anyone / 03 Jun 2025 / safari ",
                            "headers": {
                              "_run": "1",
                              "_tester": "anyone",
                              "_createdDate": "03 Jun 2025",
                              "_createdTime": "14:28:15",
                              "_tags": "ALL",
                              "browser": "safari",
                            },
                            "assignee": {
                              "id": "_anyone",
                              "name": "anyone",
                              "email": ""
                            },
                            "results": {
                              "2": { "result": "blocked", "comment": "no cigar" },
                              "3":    { "result": "fail" },
                              "4":    { "result": "fail" },
                              "5":    { "result": "", "issue": "TPT-124" }
                            },
                            "progress": {
                              "total": 4,
                              "pass": 0,
                              "fail": 2,
                              "block": 1,
                              "query": 0,
                              "summary": "Pass:0 Fail:2 Block:1 Query:0 Total:3/4"
                            },
                          }
                        ],
                        "progress": {
                          "total": 4,
                          "pass": 0,
                          "fail": 2,
                          "block": 1,
                          "query": 0,
                          "summary": "Pass:0 Fail:2 Block:1 Query:0 Total:3/4"
                        }
                      },
                      "context": {
                        "project": { "id": 3, "name": "Example Project", "description": "An example project", "created": "2020-10-22T13:34:26.571000+00:00", "bugPattern": "" },
                        "folderPath": { "folders": [], "path": "/" }
                      }
                    }
                noTests:
                  summary: /scripts/23?tests=none
                  value: |
                    {
                      "script": {
                        "id": 23,
                        "name": "Hello World",
                        "description": "An example script to fetch from the API",
                        "comments": "Comments to be included in the report for this script",
                        "created": "2020-10-23T10:41:59.834000+00:00",
                        "archived": false,
                        "fields": [
                          { "id": "_run", "label": "number", "show": true },
                          { "id": "_tester", "label": "tester", "show": true },
                          { "id": "_createdDate", "label": "date", "show": true },
                          { "id": "_createdTime", "label": "time", "show": false },
                          { "id": "_tags", "label": "tag filter", "show": false },
                          { "id": "browser", "label": "Browser", "show": true }
                        ],
                        "runs": [
                          {
                            "id": "1",
                            "created": "2025-06-03T14:28:15.466",
                            "state": "complete",
                            "label": "1 / anyone / 03 Jun 2025 / safari ",
                            "headers": {
                              "_run": "1",
                              "_tester": "anyone",
                              "_createdDate": "03 Jun 2025",
                              "_createdTime": "14:28:15",
                              "_tags": "ALL",
                              "browser": "safari",
                            },
                            "assignee": {
                              "id": "_anyone",
                              "name": "anyone",
                              "email": ""
                            },
                            "results": {
                              "2": { "result": "blocked", "comment": "no cigar" },
                              "3":    { "result": "fail" },
                              "4":    { "result": "fail" },
                              "5":    { "result": "", "issue": "TPT-124" }
                            },
                            "progress": {
                              "total": 4,
                              "pass": 0,
                              "fail": 2,
                              "block": 1,
                              "query": 0,
                              "summary": "Pass:0 Fail:2 Block:1 Query:0 Total:3/4"
                            },
                          }
                        ],
                        "progress": {
                          "total": 4,
                          "pass": 0,
                          "fail": 2,
                          "block": 1,
                          "query": 0,
                          "summary": "Pass:0 Fail:2 Block:1 Query:0 Total:3/4"
                        }
                      }
                      "context": {
                        "project": { "id": 3, "name": "Example Project", "description": "An example project", "created": "2020-10-22T13:34:26.571000+00:00" },
                        "folderPath": { "folders": [], "path": "/" }
                      }
                    }
  /scripts/{script_id}/runs:
    post:
      summary: Add a test run
      description: >-
        Adds a test run to the script script_id.


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


        For now, there’s no API support for creating retests of test runs.


        The test run can optionally include test results.


        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).
      tags:
        - ◉ Run Endpoints
      parameters:
        - name: script_id
          in: path
          required: true
          schema:
            type: integer
          description: The script ID.
      requestBody:
        required: true
        content:
          application/json:
            examples:
              default:
                summary: /scripts/23/runs
                value: >
                  { "headers": { "build": "1.1.1", "weather": "fair" },
                  "results": { "2": "pass", "3": "fail" } }
      x-codeSamples:
        - lang: bash
          label: curl
          source: >
            curl -X POST
            "https://api.testpad.com/api/v1/scripts/23/runs"              
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "headers": {"build": "1.1.1", "weather": "fair"},
              "results": {"2": "pass", "3": "fail"}
            }

            EOF
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              examples:
                default:
                  summary: /scripts/23/runs
                  value:
                    run:
                      id: '6'
                      headers:
                        _run: '6'
                        _tags: ALL
                        build: 1.1.1
                        weather: fair
                      results:
                        '2':
                          result: pass
                        '3':
                          result: fail
  /projects/{project_id}/notes:
    get:
      summary: Get a list of notes at the top-level of a project
      description: >-
        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`.
      tags:
        - ◉ Note Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          schema:
            type: integer
          description: The project ID.
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X GET "https://api.testpad.com/api/v1/projects/119/notes"
                 -H "Authorization: apikey $ACCESS_TOKEN"
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/notes
                  value:
                    notes:
                      - id: n1
                        name: A note item in project 119
                        type: note
                      - id: n2
                        name: Another note item in project 119
                        type: note
    post:
      summary: Create a note in a project
      description: >-
        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".
      tags:
        - ◉ Note Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          schema:
            type: integer
          description: The project ID.
        - name: insert
          in: query
          required: false
          schema:
            type: string
          description: >
            Controls where the note will be created within the top-level items


            `first` (default) — the note is placed at the top of the project.  

            `last` — the note is placed at the end of the project's contents.  

            `N` - integer — the note is placed after the Nth item in the
            project.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                  description: >
                    The contents of the new note, effectively its "name" in the
                    same way scripts and folders

                    have names that are displayed as items in folders.
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X POST "https://api.testpad.com/api/v1/projects/119/notes"
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "name": "A note created by the API"
            }
            EOF
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/notes
                  value:
                    note:
                      id: n5
                      name: A note created by the API
                      type: note
  /projects/{project_id}/folders/{folder_id}/notes:
    get:
      summary: Get the list of notes in a folder
      description: >-
        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`.
      tags:
        - ◉ Note Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          schema:
            type: integer
          description: The project ID.
        - name: folder_id
          in: path
          required: true
          schema:
            type: string
          description: The folder ID.
      x-codeSamples:
        - lang: bash
          label: curl
          source: >
            curl -X GET
            "https://api.testpad.com/api/v1/projects/119/folders/f2/notes"
                 -H "Authorization: apikey $ACCESS_TOKEN"
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/folders/f2/notes
                  value:
                    notes:
                      - id: n7
                        name: A note in folder f2 of project 119
                        type: note
    post:
      summary: Create a note in a folder
      description: >-
        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`.
      tags:
        - ◉ Note Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          schema:
            type: integer
          description: The project ID.
        - name: folder_id
          in: path
          required: true
          schema:
            type: string
          description: The folder ID.
        - name: insert
          in: query
          required: false
          schema:
            type: string
          description: >
            Controls where the note will be created within the top-level items


            `first` (default) — the note is placed at the top of the project.  

            `last` — the note is placed at the end of the project's contents.  

            `N` - integer — the note is placed after the Nth item in the
            project.
      requestBody:
        required: true
        content:
          application/json:
            examples:
              default:
                summary: /projects/119/folders/f2/notes?insert=last
                value:
                  name: A note created by the API
      x-codeSamples:
        - lang: bash
          label: curl
          source: >
            curl -X POST
            "https://api.testpad.com/api/v1/projects/119/folders/f2/notes?insert=last"
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "name": "A note created by the API"
            }

            EOF
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/folders/f2/notes?insert=last
                  value:
                    note:
                      id: n7
                      name: A note created by the API
  /projects/{project_id}/notes/{note_id}:
    patch:
      summary: Modify a note
      description: >-
        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`.
      tags:
        - ◉ Note Endpoints
      parameters:
        - name: project_id
          in: path
          required: true
          schema:
            type: integer
          description: The project ID.
        - name: note_id
          in: path
          required: true
          schema:
            type: string
          description: The note ID.
      requestBody:
        required: true
        content:
          application/json:
            examples:
              default:
                summary: /projects/119/notes/n5
                value:
                  name: A note modified by the API
      x-codeSamples:
        - lang: bash
          label: curl
          source: |
            curl -X PATCH "https://api.testpad.com/api/v1/projects/119/notes/n5"
                 -H "Authorization: apikey $ACCESS_TOKEN"
                 --data-binary @- << 'EOF'
            {
              "name": "A note modified by the API"
            }
            EOF
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              examples:
                default:
                  summary: /projects/119/notes/n5
                  value:
                    note:
                      id: n5
                      name: A note modified by the API
components:
  parameters:
    AuthorizationHeader:
      name: Authorization
      in: header
      description: Used to supply your API ACCESS TOKEN.
      required: true
      schema:
        type: string
      example: apikey YOUR_TOKEN_HERE
  schemas:
    FieldDef:
      type: object
      title: field definitions
      description: >
        A field definition object, consisting of:


        - **id** (required) - the ID of the field, can be built-in or
        user-supplied


        - **label** (optional) - not allowed for built-in fields whose ids start
        with `_`


        - **show** (optional) - defaults to `true`
      properties:
        id:
          type: string
          description: >
            The field ID. Built-in field IDs start with `_`. User-supplied field
            IDs cannot start with `_`. (e.g. `_run`, `_tester`, `_createdDate`,
            `_createdTime`, `_tags`).
        label:
          type: string
          description: >-
            The text displayed for the field (omit when referencing built-in
            fields as their label cannot be changed)
        show:
          type: boolean
          description: Whether to show this field in summaries (default true).
      required:
        - id
      additionalProperties: false
    FieldsInput:
      type: array
      description: >
        A list of field definitions, with three options for how to supply them:

        - as a **string**, used as the field ID or label, with IDs derived by
        converting spaces to underscores, and labels derived by converting
        underscores to spaces

        - as a **parenthesized string**, e.g. `(field)`, which works as for a
        string-supplied field, except the parantheses imply the field should be
        show:false (i.e. hidden)

        - as an **object** - a `FieldDef`
      items:
        oneOf:
          - $ref: '#/components/schemas/FieldDef'
          - type: string
    TestInput:
      type: object
      description: The text of a single line test prompt, along with optional tags.
      properties:
        text:
          type: string
          description: The text of the test line.
        tags:
          type: string
          description: Optional tags for this test line, comma-separated.
      required:
        - text
      additionalProperties: false
    TestsInput:
      description: >
        A collection of tests, each test a separate line of text.

        Supply test lines as one of:

        1. a single multiline string, OR 1. an array of strings, OR 1. an array
        of objects (TestInput).
      oneOf:
        - type: string
        - type: array
          items:
            type: string
        - type: array
          items:
            $ref: '#/components/schemas/TestInput'
    HeadersInput:
      type: object
      description: >
        A map of header field IDs to their string values.   Each property name
        is a header ID (for example `"browser"`, `"platform"`, or a built-in
        header such as `"_tester"`).   Each property value is the header's value
        as a string.
      additionalProperties:
        type: string
    Result:
      type: object
      description: A single result value, optionally with comments and issue numbers.
      properties:
        result:
          type: string
          enum:
            - pass
            - fail
            - blocked
            - query
        comment:
          type: string
          description: Optional comment
        issue:
          type: string
          description: Optional issue number or comma-separated list of issue numbers.
      required:
        - result
      additionalProperties: false
    ResultValueInput:
      oneOf:
        - type: string
          enum:
            - pass
            - fail
            - blocked
            - query
        - $ref: '#/components/schemas/Result'
    ResultsInput:
      type: object
      description: >
        Map of **test ID → result**.   Keys are test IDs (test numbers supplied
        as a string to work as an object key).   Values are either a simple
        status ("pass", "fail" etc) or a ResultObject.
      additionalProperties:
        $ref: '#/components/schemas/ResultValueInput'
    RunInput:
      type: object
      description: A single test run with headers and results.
      properties:
        id:
          type: integer
          description: Run identifier
        headers:
          $ref: '#/components/schemas/HeadersInput'
        results:
          $ref: '#/components/schemas/ResultsInput'
      required:
        - results
      additionalProperties: false
    RunsInput:
      type: array
      description: |
        List of runs to include with the script.    
      items:
        $ref: '#/components/schemas/RunInput'
    ScriptInput:
      type: object
      description: >
        Represents a script object when supplied as input, including its
        metadata, fields, tests, and test runs.
      properties:
        name:
          type: string
          description: >
            The name of the script.   Defaults to **"New Script"** if not
            supplied.
        description:
          type: string
          description: |
            Optional description for the script.   Left empty if not supplied.
        fields:
          $ref: '#/components/schemas/FieldsInput'
        tests:
          $ref: '#/components/schemas/TestsInput'
        runs:
          $ref: '#/components/schemas/RunsInput'
      additionalProperties: false
    Fields:
      type: array
      description: |
        A list of fields a script is using
      items:
        $ref: '#/components/schemas/FieldDef'
    Test:
      type: object
      description: A single test prompt row, including possible tags
      properties:
        id:
          type: integer
          description: the ID of the test row
        text:
          type: string
          description: The text of the test line.
        tags:
          type: string
          description: Any tags for this test line, comma-separated.
        indent:
          type: integer
          description: >
            How indented this test row is in the outline hierarchy of the
            script. Top level title rows are indent=0. Child rows of top level
            title rows are indent=1. And so on.
    Tests:
      description: >
        A collection of tests, each test a separate line of text.

        The format of the collection depends on the `tests` URL parameter (see
        [Common URL Parameters](/docs/common-parameters.md)).
      oneOf:
        - type: string
        - type: array
          items:
            type: string
        - type: array
          items:
            $ref: '#/components/schemas/Test'
    Headers:
      type: object
      description: The header values for the header fields of a test run
      properties:
        _run:
          type: string
          description: Run identifier
        _createdDate:
          type: string
          description: The date (day) this test run was created
        _createdTime:
          type: string
          description: The time of day that this test run was created
        _tags:
          type: string
          description: >-
            The value of the Tags Filter field, specifying which tags to use for
            filtering tests by tag
        _tester:
          type: string
          description: >-
            The displayable name of the assignee of this test run, might be a
            user's name, or an alias if using Guest Testing
      additionalProperties:
        type: string
        description: Along with any custom header fields
    Results:
      type: object
      description: >
        Sparse map of the result values for tests in this script for a test run.
        The keys are the string version of a test row ID. The values are Result
        objects.
      additionalProperties:
        $ref: '#/components/schemas/Result'
    Run:
      type: object
      description: A single test run with headers and results.
      properties:
        id:
          type: integer
          description: >-
            The run identifier, might come back as a string in the form `1.1` if
            this is a retest test run
        created:
          type: string
          description: The timestamp of when this test run was created
        assignee:
          type: object
          description: An object describing who this test run has been assigned to
          properties:
            email:
              type: string
              description: >-
                the last email address that an invitation to make this test run
                was sent to (normally used for Guest Testing)
            id:
              type: string
              description: >-
                the user ID of who this has been assigned to, or `_anyone` if
                not assigned
            name:
              type: string
              description: >-
                the name of the assignee of this test run, either the name
                associated with a known user in the account, or an alias
                supplied for e.g. when guest testing
        headers:
          $ref: '#/components/schemas/Headers'
        results:
          $ref: '#/components/schemas/Results'
      required:
        - results
      additionalProperties: false
    Runs:
      type: array
      description: The list of test runs in a script.
      items:
        $ref: '#/components/schemas/Run'
    ProgressTerse:
      type: object
      description: >
        Terse progress summary containing only text-based counts and summary
        lines.
      properties:
        counts:
          type: string
          description: >
            Compact count summary — space-separated values in order: pass, fail,
            blocked, query, total.
        summary:
          type: string
          description: Readable one-line text summary.
    ProgressFull:
      type: object
      description: >
        Full progress summary including numeric totals and percentages, along
        with textual summaries. Note that percentages are integer, and rounded
        up to 1 if non-zero, in a way that they all still sum to 100.
      properties:
        passing:
          type: integer
          description: Number of passing tests.
        passingPc:
          type: integer
          description: Percent of total that passed.
        fail:
          type: integer
          description: Number of failed tests.
        failPc:
          type: integer
          description: Percent of total that failed.
        blocked:
          type: integer
          description: Number of blocked tests.
        blockedPc:
          type: integer
          description: Percent of total that were blocked.
        query:
          type: integer
          description: Number of tests in query state.
        queryPc:
          type: integer
          description: Percent of total that are in query state.
        tried:
          type: integer
          description: Number of tests attempted.
        triedPc:
          type: integer
          description: Percent of total that were attempted.
        remain:
          type: integer
          description: Number of remaining tests.
        remainPc:
          type: integer
          description: Percent of total remaining.
        total:
          type: integer
          description: Total number of tests.
        counts:
          type: string
          description: >
            Compact count summary — space-separated values in order: pass, fail,
            blocked, query, total.
        summary:
          type: string
          description: Readable text summary.
    Progress:
      description: >
        Progress object — may be either **terse** or **full** format depending
        on the URL parameter `progress`.
      oneOf:
        - $ref: '#/components/schemas/ProgressTerse'
        - $ref: '#/components/schemas/ProgressFull'
    Script:
      type: object
      description: >
        Represents a script object when returned in responses, including its
        metadata, fields, tests, and test runs.
      properties:
        id:
          type: integer
          description: |
            The ID of the script, generated by the server.
        name:
          type: string
          description: |
            The name of the script.  
        description:
          type: string
          description: |
            Description for the script.
        created:
          type: string
          description: |
            The timestamp for when the script was created.
        archived:
          type: boolean
          description: >
            Whether the script has been archived within its project or not. Note
            that if the project itself has been archived, this property might
            still say `false` - it only relates to whether the script has been
            archived within the project.
        fields:
          $ref: '#/components/schemas/Fields'
        tests:
          $ref: '#/components/schemas/Tests'
        runs:
          $ref: '#/components/schemas/Runs'
        progress:
          $ref: '#/components/schemas/Progress'
      additionalProperties: false
