Endpoints

Test Cases

How to work with test cases using the public API

The test cases endpoints allow you to retrieve information about test cases in your project. This can be useful for planning test runs and monitoring your test coverage.

Types of Test Cases

In QA Sphere, there are three types of test cases:

  1. Standalone Test Case: These are the standard test cases.
  2. Template Test Case: Similar to standalone test cases, but they can include parameters within ${} in their title, preconditions, and steps. These parameters can be replaced with specific values to generate multiple test cases from the same template.
  3. Filled Test Cases: Automatically created by the system by substituting parameter values in template test cases. They inherit all properties from the parent template test case.
  • Users can directly create standalone and template test cases. When creating template test cases, users can specify a list of values for the parameters, which the system uses to automatically generate the corresponding filled test cases.
  • Updates to a template test case will also update the corresponding filled test cases.
  • Deletion is permitted for all three types of test cases. Deleting a template test case will also delete the associated filled test cases. Deleting a filled test case will only remove that specific test case.
  • Test runs include only standalone and filled test cases.

List Project Test Cases

GET/api/public/v0/project/{project_id}/tcase

Retrieves all test cases within a project based on the filters provided in the request query parameters.

Path Parameters

  • project_id: The project identifier (can be either the project code or UUID)

Query Parameters

All query parameters are optional and some can be specified multiple times using the format param=value1&param=value2&param=value3.

ParameterTypeMultipleDescriptionAllowed ValuesExample
offsetnumbernoNumber of rows to skip before returning results. Combine with limit for offset-based pagination.offset=10
limitnumbernoMaximum number of test cases to return (0–5000). May be 0 to return only the total count (no rows).limit=10
pagenumbernoDeprecated — use offset instead. 1-based page number. Ignored when offset is set. If limit is omitted, a default of 10 is applied.page=1
sortFieldstringnoField to sort byid, seq, folder_id, author_id, pos, title, priority, created_at, updated_at, legacy_idsortField=title
sortOrderstringnoSort order (requires sortField; default: desc)asc, descsortOrder=desc
typesstringyesFilter test cases by typestandalone, template, filledtypes=standalone
searchstringnoFilter test cases by title (case insensitive, partial matches)search=ui
foldersnumberyesFilter test cases by folder ID (does not consider child folders)folders=10&folders=12
tagsnumberyesFilter test cases by tag IDtags=12
prioritiesstringyesFilter test cases by priorityhigh, medium, lowpriorities=low
draftboolnoFilter test cases by draft statustrue, falsedraft=true
templateTCaseIdsstringyesFilter test cases by their parent template test case identifierstemplateTCaseIds=1CEPaUhuR_yNsLvcbYJhw46
requirementIdsstringyesFilter test cases by requirement IDrequirementIds=1CEPaUhuR_abc123def456
cf_${custom field system name}stringyesFilter test cases by custom field valueThe values for custom fields are defined under Settings > Custom Fieldscf_automation=Automated
includestringyesInclude additional fields in the response which are omitted by defaultsteps, tags, project, folder, path, requirements, customFields, parameterValuesinclude=steps
  • Use pagination when project contains large number of test cases
  • Only include necessary non-default fields
  • Different filters are combined with AND logic
  • Multiple values for the same filter are combined with OR logic

Example Request

Fetch all test cases with default fields

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase

Fetch all test cases with "Automation" custom field to be "Automated"

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?cf_automation=Automated

Fetch all test cases with "Known Issue" custom field to be "Yes"

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?cf_known_issue=Yes

Fetch 20 test cases sorted by title in ascending order

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?limit=20&sortField=title&sortOrder=asc

Skip the first 90 test cases and return the next 15 — or, return 15 rows starting from 0-based index 90

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?offset=90&limit=15&sortField=pos&sortOrder=asc

Fetch all draft test cases

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?draft=true

Fetch 10 most recent added test cases

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?limit=10&sortField=created_at&sortOrder=desc

Fetch test cases with "backend" in their title

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?search=backend

Fetch test cases with "backend" in their title and include custom fields

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?search=backend&include=customFields

Fetch all filled test cases corresponding to template test case ID '1CEPaUhuR_yNsLvcbYJhw46'

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?template_tcase_ids=1CEPaUhuR_yNsLvcbYJhw46

Fetch test cases linked to a specific requirement

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?requirementIds=1CEPaUhuR_abc123def456

Fetch test cases linked to multiple requirements (OR logic)

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  "https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase?requirementIds=1CEPaUhuR_abc123def456&requirementIds=1CEPaUhuR_xyz789ghi012"

Response Fields

{
  total: number,                  // Total number of filtered test cases
  offset?: number,                // The offset that was applied (present when pagination was applied)
  limit?: number,                 // The limit that was applied (present when pagination was applied)
  page?: number,                  // **Deprecated**. Echo of the page that was requested (present only if `page` was used in the request)
  data: Array<{                   // List of test case objects
    id: string                    //   Unique identifier of the test case
    legacyId: string              //   Legacy identifier of the test case. Empty string if the test case has no legacy ID
    version: number               //   Version of the test case. Updates to test (except folder/pos) creates a new version
    type: string                  //   Type of the test case (`standalone` | `template` | `filled`)
    title: string                 //   Title of the test case
    seq: number                   //   Sequence number of the test case. Test cases in a project are assigned incremental sequence numbers
    folderId: number              //   Identifier of the folder where the test case is placed
    pos: number                   //   Ordered position (0 based) of the test case in its folder
    priority: string              //   Priority of the test case (`high` | `medium` | `low`)
    comment: html                 //   Test case precondition text. DEPRECATED, usable but prefer precondition object below
    precondition: {
      projectId: string,             // Project id the precondition belongs to. Same as test cases'
      id: number,                    // Id of the precondition. Not useful unless the precondition is shared
      version: number,               // Version of the precondition
      title?: string,                // Title of the precondition. Only populated for shared
      type: 'standalone' | 'shared', // Type of the precondition
      text: html,                    // Actual text contents of the precondition
      isLatest: boolean,             // Whether precondition's version is latest or not
      createdAt: string,
      updatedAt: string,
      deletedAt?: string,
    }
    files: Array<{                //   List of files attached to the test case
      id: string                  //     Unique identifier of the file
      fileName: string            //     Name of the file
      mimeType: string            //     Mime type of the file
      size: number                //     Size of the file
      url: string                 //     URL of the file
    }>
    links: Array<{                //   Additional links relevant to the test case
      text: string                //     Title of the link
      url: string                 //     URL of the link
    }>
    authorId: number              //   Unique identifier of the user who added the test case
    isDraft: boolean              //   Whether the test case is still in draft state
    isLatestVersion: boolean      //   Whether this is the latest version of the test case
    isEmpty: boolean              //   Whether the test case is empty (has no comment and steps)
    templateTCaseId?: string      //   Corresponding template test case ID, if it is a filled test case
    numFilledTCases? number       //   Number of corresponding filled test cases, if it is a template test case
    createdAt: string             //   Test case creation time (ISO 8601 format)
    updatedAt: string             //   Test case updation time (ISO 8601 format)

    // Non default fields
    customFields: {               //   Custom fields defined for the test case
      [key: string]: {            //     Key-value pairs of custom field system names and corresponding details for the test case
        value: string             //       Current value
        isDefault: boolean        //       Whether default value is set by the system or selected by the user
      }
    }
    tags: Array<{                 //   List of test case tags
      id: number                  //     Unique identifier of the tag
      title: string               //     Title of the tag
    }>
    steps: Array<{                //   List of test case steps
      id: number                  //     Unique identifier of the step
      type: string                //     Type of the step (standalone | shared)
      version: number             //     Version of the step (always 1 for standalone steps)
      isLatest: boolean           //     Whether this is the latest version of the step (always true for standalone steps)
      title?: string              //     Title of the step (only for shared steps)
      subSteps?: Array<{          //     List of sub steps (only for shared steps)
        id: number                //       Unique identifier of the step
        type: string              //       Type of the step (shared_sub_step)
        version: number           //       Version of the step (same as parent step)
        isLatest: boolean         //       Whether this is the latest version (same as parent step)
        description: html         //       Details of the sub step
        expected: html            //       Expected result from the sub step
        deletedAt?: string        //       Date the sub step was deleted on
      }>
      description?: html          //     Details of step (only for standalone steps)
      expected?: html             //     Expected result from the step (only for standalone steps)
      deletedAt?: string          //     Date the step was deleted on
    }>
    requirements: Array<{         // 	 Test case requirement (currently only single requirement is supported on UI)
      id: string                  //     Unique identifier of the requirement
      text: string                //     Title of the requirement
      url: string                 //     URL of the requirement
    }>
    parameterValues: {            //   The details of corresponding filled tcases (relevant only for template tcases)
      tcaseId: string             //     ID of the filled tcase
      tcaseVersion: number        //     Version of the filled tcase
      values: {                   //     Values corresponding to the parameters in the template tcase for this filled tcase
        [key: string]: string
      }
    }
    folder: {                     //   Details of the folder where the test case is placed
      id: number                  //     Unique identifier for the folder
      title: string               //     Name of the folder
      comment: html               //     Additional notes or description
      pos: number                 //     Position of the folder among its siblings
      parentId: number            //     ID of the parent folder (0 for root folders)
      projectId: string           //     ID of the project the folder belongs to
    },
    path: Array<{                 //   Path to the folder where the test cases is placed
      id: number                  //     Unique identifier for the folder
      title: string               //     Name of the folder
      comment: html               //     Additional notes or description
      pos: number                 //     Position of the folder among its siblings
      parentId: number            //     ID of the parent folder (0 for root folders)
      projectId: string           //     ID of the project the folder belongs to
    }>
    project: {                    //   Details of project to which the test case belong
      id: string                  //     Unique identifier of the project
      code: string                //     Short code of the project
      title: string               //     Title of the project
      overviewTitle: string       //     Title of the project overview
      overviewDescription: html   //     Project Overview
      links: {                    //     Links relevant to the project
        text: string              //       Title of the link
        url: string               //       URL of the link
      }
      archivedAt: string          //     Project archival time (ISO 8601 format)
      createdAt: string           //     Project creation time (ISO 8601 format)
      updatedAt: string           //     Project updation time (ISO 8601 format)
    }
  }>
}

Example Response

{
  "total": 4,
  "offset": 1,
  "limit": 2,
  "data": [
    {
      "id": "1CJg36j1c_yFYPRcmZaoqp3",
      "version": 6,
      "legacyId": "",
      "seq": 55,
      "type": "standalone",
      "folderId": 26,
      "pos": 0,
      "title": "User should see the content according to the \"About Us\" information",
      "priority": "high",
      "comment": "<p>The \"About Us\" page is opened</p>",
      "precondition": {
        "projectId": "2HKj57k3z_YXYQVTdnPqrs8",
        "id": 2,
        "version": 3,
        "type": "standalone",
        "text": "<p>The \"About Us\" page is opened</p>",
        "isLatest": true,
        "createdAt": "2025-03-25T10:48:34.66935+02:00",
        "updatedAt": "2025-03-25T10:48:34.66935+02:00"
      },
      "authorId": 1,
      "files": [
        {
          "id": "89f7a73e-043c-4fe1-beb3-9e8d8df55f28",
          "fileName": "Screencast from 24-03-25 14:27:33.webm",
          "mimeType": "video/webm",
          "size": 555431
        }
      ],
      "links": [],
      "isDraft": false,
      "isLatestVersion": true,
      "isEmpty": false,
      "createdAt": "2025-03-25T10:48:14.243475+02:00",
      "updatedAt": "2025-03-25T10:48:14.243475+02:00"
    },
    {
      "id": "1CJg36j28_EaAHxNiNQNNTn",
      "version": 6,
      "legacyId": "",
      "seq": 56,
      "type": "standalone",
      "folderId": 26,
      "pos": 1,
      "title": "User should place the order successfully after entering valid data in all required fields and selecting the \"Card Payment\" payment",
      "priority": "high",
      "comment": "<ol><li><p>The \"Checkout\" page is opened</p></li><li><p>There are pizzas, drinks and desserts</p></li></ol>",
      "authorId": 1,
      "files": [
        {
          "id": "bf5fcc05-44a2-46b2-87fb-2501cfedb1f7",
          "fileName": "Screenshot 2025-01-15 18:54:44.png",
          "mimeType": "image/png",
          "size": 89567
        }
      ],
      "links": [],
      "isDraft": false,
      "isLatestVersion": true,
      "isEmpty": false,
      "createdAt": "2025-03-25T10:48:34.66935+02:00",
      "updatedAt": "2025-03-25T10:48:34.66935+02:00"
    }
  ]
}

Get Test Case

GET/api/public/v0/project/{project_id}/tcase/{tcase_or_legacy_id}

Get details of a single test case using its ID, sequence or legacy ID.

Path Parameters

  • project_id: The project identifier (can be either the project code or UUID)
  • tcase_or_legacy_id: The test case identifier (can be one of test case UUID, sequence or legacy ID)

Example Request

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/1

Response Fields

{
  id: string                    // Unique identifier of the test case
  legacyId: string              // Legacy identifier of the test case. Empty string if the test case has no legacy ID
  version: number               // Version of the test case. Updates to test (except folder/pos) creates a new version
  type: string                  // Type of the test case (`standalone` | `template` | `filled`)
  title: string                 // Title of the test case
  seq: number                   // Sequence number of the test case. Test cases in a project are assigned incremental sequence numbers
  folderId: number              // Identifier of the folder where the test case is placed
  pos: number                   // Ordered position (0 based) of the test case in its folder
  priority: string              // Priority of the test case (`high` | `medium` | `low`)
  comment: html                //   Test case precondition text. DEPRECATED, usable but prefer precondition object below
  precondition: {
    projectId: string,             // Project id the precondition belongs to. Same as test cases'
    id: number,                    // Id of the precondition. Not useful unless the precondition is shared
    version: number,               // Version of the precondition
    title?: string,                // Title of the precondition. Only populated for shared
    type: 'standalone' | 'shared', // Type of the precondition
    text: html,                    // Actual text contents of the precondition
    isLatest: boolean,             // Whether precondition's version is latest or not
    createdAt: string,
    updatedAt: string,
    deletedAt?: string,
  }
  steps: Array<{                // List of test case steps
    id: number                  //   Unique identifier of the step
    type: string                //   Type of the step (standalone | shared)
    version: number             //   Version of the step (always 1 for standalone steps)
    isLatest: boolean           //   Whether this is the latest version of the step (always true for standalone steps)
    title?: string              //   Title of the step (only for shared steps)
    subSteps?: Array<{          //   List of sub steps (only for shared steps)
      id: number                //     Unique identifier of the step
      type: string              //     Type of the step (shared_sub_step)
      version: number           //     Version of the step (same as parent step)
      isLatest: boolean         //     Whether this is the latest version (same as parent step)
      description: html         //     Details of the sub step
      expected: html            //     Expected result from the sub step
      deletedAt?: string        //     Date the sub step was deleted on
    }>
    description?: html          //   Details of step (only for standalone steps)
    expected?: html             //   Expected result from the step (only for standalone steps)
    deletedAt?: string          //   Date the step was deleted on
  }>
  tags: Array<{                 // List of test case tags
    id: number                  //   Unique identifier of the tag
    title: string               //   Title of the tag
  }>
  files: Array<{                // List of files attached to the test case
    id: string                  //   Unique identifier of the file
    fileName: string            //   Name of the file
    mimeType: string            //   Mime type of the file
    size: number                //   Size of the file
    url?: string                //   URL of the file (optional, not present in sample)
  }>
  requirements: Array<{         // Test case requirement (currently only single requirement is supported on UI)
    id: string                  //   Unique identifier of the requirement
    text: string                //   Title of the requirement
    url: string                 //   URL of the requirement
  }>
  links: Array<{                // Additional links relevant to the test case
    text: string                //   Title of the link
    url: string                 //   URL of the link
  }>
  customFields: {               // Custom fields defined for the test case
    [key: string]: {            //   Key-value pairs of custom field system names and corresponding details for the test case
      value: string             //     Current value
      isDefault: boolean        //     Whether default value is set by the system or selected by the user
    }
  }
  parameterValues: {            // The details of corresponding filled tcases (relevant only for template tcases)
    tcaseId: string             //   ID of the filled tcase
    tcaseVersion: number        //   Version of the filled tcase
    values: {                   //   Values corresponding to the parameters in the template tcase for this filled tcase
      [key: string]: string
    }
  }
  authorId: number              // Unique identifier of the user who added the test case
  isDraft: boolean              // Whether the test case is still in draft state
  isLatestVersion: boolean      // Whether this is the latest version of the test case
  isEmpty: boolean              // Whether the test case is empty (has no comment and steps)
  templateTCaseId?: string      // Corresponding template test case ID, if it is a filled test case
  numFilledTCases? number       // Number of corresponding filled test cases, if it is a template test case
  createdAt: string             // Test case creation time (ISO 8601 format)
  updatedAt: string             // Test case updation time (ISO 8601 format)
}

Sample Response

{
  "id": "1CJg36j1c_yFYPRcmZaoqp3",
  "version": 6,
  "legacyId": "",
  "seq": 55,
  "type": "standalone",
  "folderId": 26,
  "pos": 0,
  "title": "User should see the content according to the \"About Us\" information",
  "priority": "high",
  "comment": "<p>The \"About Us\" page is opened</p>",
  "precondition": {
    "projectId": "2HKj57k3z_YXYQVTdnPqrs8",
    "id": 2,
    "version": 3,
    "type": "standalone",
    "text": "<p>The \"About Us\" page is opened</p>",
    "isLatest": true,
    "createdAt": "2025-03-25T10:48:14.243475+02:00",
    "updatedAt": "2025-03-25T10:48:14.243475+02:00"
  },
  "authorId": 1,
  "files": [
    {
      "id": "89f7a73e-043c-4fe1-beb3-9e8d8df55f28",
      "fileName": "Screencast from 24-03-25 14:27:33.webm",
      "mimeType": "video/webm",
      "size": 555431
    }
  ],
  "links": [],
  "requirements": [
    {
      "text": "AUTO-REQ-2 Automated Tests Requirements",
      "url": "https://github.com/Hypersequent/bistro-e2e/docs/automated-testing/requirements#auto-req-2",
      "id": "1CJg36j1s_WwGRdtSYt43VZ"
    }
  ],
  "tags": [
    { "id": 1, "title": "About Us" },
    { "id": 206, "title": "automation" },
    { "id": 3, "title": "REQ-4" }
  ],
  "steps": [
    {
      "id": 1,
      "type": "standalone",
      "version": 1,
      "isLatest": true,
      "description": "<p>Automated validation of About Us content</p>",
      "expected": "<p>Content matches expected About Us information</p>"
    },
    {
      "id": 2,
      "type": "shared",
      "version": 3,
      "isLatest": true,
      "title": "About us validations",
      "subSteps": [
        {
          "id": 3,
          "type": "shared_sub_step",
          "version": 3,
          "isLatest": true,
          "description": "<p>Verify company name and logo are displayed correctly</p>",
          "expected": "<p>Company name and logo match branding guidelines</p>"
        },
        {
          "id": 4,
          "type": "shared_sub_step",
          "version": 3,
          "isLatest": true,
          "description": "<p>Check mission statement content</p>",
          "expected": "<p>Mission statement matches approved text</p>"
        },
        {
          "id": 5,
          "type": "shared_sub_step",
          "version": 3,
          "isLatest": true,
          "description": "<p>Validate team member information</p>",
          "expected": "<p>Team member profiles are accurate and complete</p>"
        }
      ]
    }
  ],
  "customFields": {
    "automation": {
      "value": "Automated",
      "isDefault": false
    },
    "known_issue": {
      "value": "No",
      "isDefault": true
    }
  },
  "isDraft": false,
  "isLatestVersion": true,
  "isEmpty": false,
  "createdAt": "2025-03-25T10:48:14.243475+02:00",
  "updatedAt": "2025-03-25T10:48:14.243475+02:00"
}

Get Test Case Count

GET/api/public/v0/project/{project_id}/tcase/count

Returns the total number of test cases that match the specified filters. If no filters are provided, returns the total count of all test cases in the project.

Path Parameters

  • project_id: The project identifier (can be either the project code or UUID)

Query Parameters

ParameterTypeDescriptionExample
foldersnumberFilter by folder IDsfolders=1&folders=2
recursivebooleanInclude test cases in subfolders (requires folders)recursive=true
tagsnumberFilter by tag IDstags=1&tags=2
prioritiesstringFilter by priority levels (high, medium, low)priorities=high&priorities=medium
draftbooleanFilter by draft statusdraft=true

Example Requests

Basic Count

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  "https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count"

Filter Examples

  1. Folder-based counting:
curl \
  -H "Authorization: ApiKey your.api.key.here" \
  "https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?folders=1&recursive=true"
  1. Priority-based counting:
curl \
  -H "Authorization: ApiKey your.api.key.here" \
  "https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?priorities=high"
  1. Tag-based counting:
curl \
  -H "Authorization: ApiKey your.api.key.here" \
  "https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?tags=1&tags=2"
  1. Draft status counting:
curl \
  -H "Authorization: ApiKey your.api.key.here" \
  "https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?draft=true"
  1. Custom field counting:
curl \
  -H "Authorization: ApiKey your.api.key.here" \
  "https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/count?cf_automation=Automated"

Response Format

{
  count: number // Total number of test cases matching the filters
}

Example Response

{
  "count": 4
}

Error Responses

Status CodeDescription
401Invalid or missing API key
403Insufficient permissions or suspended tenant
404Project not found
400Invalid filter parameters
500Internal server error

Use Cases

  • Monitor test coverage by counting test cases across different folders
  • Track high-priority test case volume
  • Review draft test case count before publishing
  • Plan test runs based on tagged test cases

Filter Behavior

  • If no filters are specified, all test cases in the project are counted
  • Different filters are combined with AND logic
  • Multiple values for the same filter are combined with OR logic
  • The recursive parameter only applies when folders is specified

Create Test Case

POST/api/public/v0/project/{project_id}/tcase

Creates a new test case in the specified project. You can create both standalone and template test cases using this endpoint.

Path Parameters

  • project_id: The project identifier (can be either the project code or UUID)

Request Body


{
  title: string             // Required: Test case title (must be between 1-511 characters)
  type: string              // Required: Type of test case (`standalone` | `template`)
  folderId: number          // Required: ID of the folder where the test case will be placed
  priority: string          // Required: Test case priority (`high` | `medium` | `low`)
  pos?: number              // Optional: Position within the folder (0-based index)
  comment?: html            // Optional: Test case precondition. DEPRECATED, if precondition object is empty, comment is used to populated precondition.text
  precondition?:            // Optional: Test case precondition
    | { sharedPreconditionId: number } // Use a shared precondition by specifying its unique id
    | { text: html }                   // Or, use a standalone precondition with text
  steps?: Array<{           // Optional: List of test case steps
    // For shared steps
    sharedStepId?: number   //   Unique identifier of the shared step

    // For standalone steps
    description?: html      //   Details of steps
    expected?: html         //   Expected result from the step
  }>
  tags?: string[]           // Optional: List of tag titles (max 255 characters each)
  requirements?: Array<{    // Optional: Test case requirement
    text: string            //  Required: Title of the requirement (must be between 1-255 characters)
    url: string             //  Required: URL of the requirement (must be between 1-255 characters)
  }>
  files?: Array<{           // Optional: Files attached to the test case
    id: string              //   Required: File identifier, typically returned by the upload file endpoint
    fileName: string        //   Required: Original file name
    mimeType: string        //   Required: MIME type of the file
    size: number            //   Required: File size in bytes
    url?: string            //   Optional: File URL returned by the upload file endpoint
  }>
  links?: Array<{           // Optional: Additional links relevant to the test case
    text: string            //   Required: Title of the link (must be between 1-255 characters)
    url: string             //   Required: URL of the link (must be between 1-255 characters)
  }>
  customFields?: {          // Optional: Custom field values.
    [key: string]: {        //   Custom field system names should be specified as keys. Only custom fields applied and enabled for a project should be specified
      isDefault: boolean    //     Whether to set the default value. Should be true only if the custom field actually has a default value
      value: string         //     Custom field value to be set. Should be specified only if not setting to the default value
    }
  }
  parameterValues?: Array<{ // Optional: Values to substitute for parameters in the filled test cases (only relevant for template types)
    values: {               //   Values for the parameters in the template test case to be substituted for this filled test case
      [key: string]: string
    }
  }>
  filledTCaseTitleSuffixParams?: string[] // Optional: Parameters to append to filled test case titles
  isDraft?: boolean               // Whether to create as draft, default false
}
  • Required fields: type, folderId, title, priority
  • Test case types: Only standalone and template can be created directly. filled test cases are automatically generated from template test cases.
  • Steps: You can use either shared steps (by sharedStepId) or standalone steps (with description and expected).
  • Custom fields: Must be created through the web UI before you can set their values via API.
  • Template test cases: Use parameterValues to define parameter substitutions that will generate filled test cases.
  • Position: If pos is not specified, the test case will be added at the end of the folder.
  • Files: Use the upload file endpoint first. Public upload responses include id and url; when attaching files to a test case, also provide the matching fileName, mimeType, and size.

Example Requests

Create a Simple Standalone Test Case

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "standalone",
    "folderId": 26,
    "title": "User should be able to login with valid credentials",
    "priority": "high",
    "precondition": {
      "text": "<p>User has valid account credentials</p>"
    },
    "isDraft": false,
    "steps": [
      {
        "description": "<p>Navigate to login page</p>",
        "expected": "<p>Login form is displayed</p>"
      },
      {
        "description": "<p>Enter valid username and password</p>",
        "expected": "<p>Credentials are accepted</p>"
      },
      {
        "description": "<p>Click login button</p>",
        "expected": "<p>User is redirected to dashboard</p>"
      }
    ],
    "tags": ["authentication", "login"],
    "requirements": [
      {
        "text": "REQ-001: User Authentication",
        "url": "https://docs.example.com/requirements/auth"
      }
    ]
  }' \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase

Create a Template Test Case with Parameters

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "template",
    "folderId": 26,
    "title": "User should be able to login with ${browser} browser on ${device}",
    "priority": "medium",
    "precondition": {
      "text": "<p>Testing login functionality across different browsers and devices</p>"
    },
    "isDraft": false,
    "steps": [
      {
        "description": "<p>Open ${browser} browser on ${device}</p>",
        "expected": "<p>Browser opens successfully</p>"
      },
      {
        "description": "<p>Navigate to login page</p>",
        "expected": "<p>Login form is displayed correctly</p>"
      },
      {
        "description": "<p>Enter valid credentials and submit</p>",
        "expected": "<p>Login is successful on ${device}</p>"
      }
    ],
    "tags": ["authentication", "cross-browser", "responsive"],
    "parameterValues": [
      {
        "values": {
          "browser": "Chrome",
          "device": "Desktop"
        }
      },
      {
        "values": {
          "browser": "Firefox",
          "device": "Desktop"
        }
      },
      {
        "values": {
          "browser": "Safari",
          "device": "Mobile"
        }
      }
    ],
    "filledTCaseTitleSuffixParams": ["browser", "device"]
  }' \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase

Create Test Case with Custom Fields

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "standalone",
    "folderId": 26,
    "title": "API endpoint validation test",
    "priority": "high",
    "precondition": {
      "text": "<p>Test API endpoint response and data validation</p>"
    },
    "isDraft": false,
    "steps": [
      {
        "description": "<p>Send GET request to /api/users endpoint</p>",
        "expected": "<p>Response status is 200</p>"
      },
      {
        "description": "<p>Validate response JSON structure</p>",
        "expected": "<p>All required fields are present</p>"
      }
    ],
    "customFields": {
      "automation": {
        "value": "Automated"
      },
      "test_type": {
        "value": "API"
      }
    },
    "tags": ["api", "validation"]
  }' \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase

Create Draft Test Case

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "standalone",
    "folderId": 26,
    "title": "Work in progress test case",
    "priority": "low",
    "precondition": {
      "text": "<p>This test case is still being developed</p>"
    },
    "isDraft": true,
    "steps": [
      {
        "description": "<p>Step 1 - to be defined</p>",
        "expected": "<p>Expected result - to be defined</p>"
      }
    ]
  }' \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase

Response Fields

{
  id: string    // Unique identifier of the created test case
  seq: number   // Sequence number of the test case in the project
}

Example Response

Status: 201 Created

{
  "id": "1CJg36j1c_yFYPRcmZaoqp3",
  "seq": 57
}

Error Responses

Status CodeDescription
400Invalid request data or validation errors
401Invalid or missing API key
403Insufficient permissions or suspended tenant
404Project or folder not found
409Position conflict or duplicate requirement
500Internal server error while creating test case

Template Test Cases

  • Template test cases use ${parameter} syntax in titles, comments, and steps
  • Parameter values are substituted when creating filled test cases
  • Multiple parameter value sets create multiple filled test cases
  • Filled test cases inherit all properties from their template parent
  • Updates to template test cases automatically update corresponding filled test cases

Update Test Case

PATCH/api/public/v0/project/{project_id}/tcase/{tcase_or_legacy_id}

Updates a test case using its ID, sequence or legacy ID. Only users with role User or higher are allowed to update test cases.

Path Parameters

  • project_id: The project identifier (can be either the project code or UUID)
  • tcase_or_legacy_id: The test case identifier (can be one of test case UUID, sequence or legacy ID)

Request Body

{
  title?: string            // Optional: Test case title (must be between 1-511 characters)
  priority?: string         // Optional: Test case priority (`high` | `medium` | `low`)
  comment?: html            // Optional: Test case precondition. DEPRECATED, if precondition object is not present but comment is, value of comment will be used to populated precondition.text
  precondition?:            // Optional: Test case precondition
    | { sharedPreconditionId: number } // Use a shared precondition by specifying its unique id
    | { text: html }                   // Or, use a standalone precondition with text
  isDraft?: boolean         // Optional: To publish a draft test case. A published test case cannot be converted to draft
  steps?: Array<{           // Optional: List of test case steps
    // For shared steps
    sharedStepId?: number   //   Unique identifier of the shared step

    // For standalone steps
    description?: html      //   Details of steps
    expected?: html         //   Expected result from the step
  }>
  tags?: string[]           // Optional: List of test case tags (title)
  requirements?: Array<{    // Optional: Test case requirement
    text: string            //   Title of the requirement (must be between 1-255 characters)
    url: string             //   URL of the requirement (must be between 1-255 characters)
  }>
  files?: Array<{           // Optional: Files attached to the test case
    id: string              //   File identifier, typically returned by the upload file endpoint
    fileName: string        //   Original file name
    mimeType: string        //   MIME type of the file
    size: number            //   File size in bytes
    url?: string            //   File URL returned by the upload file endpoint
  }>
  links?: Array<{           // Optional: Additional links relevant to the test case
    text: string            //   Title of the link (must be between 1-255 characters)
    url: string             //   URL of the link (must be between 1-255 characters)
  }>
  customFields?: {          // Optional: Custom field values to update. Only specified custom fields are updated, others are left as is
    [key: string]: {        //   Custom field system names should be specified as keys. Only custom fields applied and enabled for a project should be specified
      isDefault: boolean    //     Whether to set the default value. Should be true only if the custom field actually has a default value
      value: string        //     Custom field value to be set. Should be specified only if not setting to the default value
    }
  }
  parameterValues?: Array<{ // Optional: Values to substitute for parameters in the filled test cases (only relevant for template types)
    tcaseId: string         //   Should be specified in order to update existing filled test case. Otherwise a new filled test case would be created. If an existing filled test case is absent in the update request, it is deleted
    values: {               //   Values for the parameters in the template test case to be substituted for this filled test case
      [key: string]: string
    }
  }>
}
  • All top-level fields are optional. Include only the top-level fields that need to be updated in the request.
  • For customFields, only the specified key values are updated; others remain unchanged.
  • Steps can be either shared or standalone. To use a shared step, specify sharedStepId. For standalone steps, specify description and/or expected.
  • Filled test case type cannot be updated.
  • If you update files, send the complete list of files you want stored on the test case.

Example Request

Switch to a Shared Precondition, Updating Test Case Title, Priority And Custom Field Value

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Changing to corresponding cursor after hovering the element",
    "precondition": {
      "id": 42
    },
    "priority": "high",
    "customFields": {
      "automation": {
        "isDefault": false,
        "value": "Automated"
      }
    }
  }' \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/1

Updating Multiple Custom Fields Values

curl \
  -H "Authorization: ApiKey your.api.key.here" \
  -H "Content-Type: application/json" \
  -d '{
    "customFields": {
      "automation": {
        "isDefault": false,
        "value": "Cannot be Automated"
      },
      "known_issue": {
        "isDefault": true
      }
    }
  }' \
  https://your-company.your-region-code.qasphere.com/api/public/v0/project/BD/tcase/56
  • Custom fields and shared steps must be created through the web UI before you can set their values via API
  • Use the system name (lowercase with underscores) of the custom field, not its display name
  • The field value must match one of the predefined options for the custom field
  • When updating custom fields, only the fields you specify will be modified
  • To remove a custom field value, you need to set it to an empty string (if allowed by the field configuration)

Example Response

Status: 200 OK

{
  "message": "Test case updated"
}

Error Responses

Status CodeDescription
400Converting a published test case to draft
401Invalid or missing API key
403Insufficient permissions or suspended tenant
404Project or test case not found
500Internal server error while updating test case

On this page

Types of Test CasesList Project Test CasesPath ParametersQuery ParametersExample RequestFetch all test cases with default fieldsFetch all test cases with "Automation" custom field to be "Automated"Fetch all test cases with "Known Issue" custom field to be "Yes"Fetch 20 test cases sorted by title in ascending orderSkip the first 90 test cases and return the next 15 — or, return 15 rows starting from 0-based index 90Fetch all draft test casesFetch 10 most recent added test casesFetch test cases with "backend" in their titleFetch test cases with "backend" in their title and include custom fieldsFetch all filled test cases corresponding to template test case ID '1CEPaUhuR_yNsLvcbYJhw46'Fetch test cases linked to a specific requirementFetch test cases linked to multiple requirements (OR logic)Response FieldsExample ResponseGet Test CasePath ParametersExample RequestResponse FieldsSample ResponseGet Test Case CountPath ParametersQuery ParametersExample RequestsBasic CountFilter ExamplesResponse FormatExample ResponseError ResponsesCreate Test CasePath ParametersRequest BodyExample RequestsCreate a Simple Standalone Test CaseCreate a Template Test Case with ParametersCreate Test Case with Custom FieldsCreate Draft Test CaseResponse FieldsExample ResponseError ResponsesUpdate Test CasePath ParametersRequest BodyExample RequestSwitch to a Shared Precondition, Updating Test Case Title, Priority And Custom Field ValueUpdating Multiple Custom Fields ValuesExample ResponseError Responses